Compare commits
38 Commits
381e284c5e
...
8c5616d7f4
Author | SHA1 | Date |
---|---|---|
Lennart Poettering | 8c5616d7f4 | |
Yu Watanabe | a3c2a9ee5d | |
Daan De Meyer | 062332f3db | |
Daan De Meyer | bc9a9177b2 | |
Daan De Meyer | e5c6dcac87 | |
Daan De Meyer | 34a7ca6db2 | |
Daan De Meyer | 397820961d | |
Yu Watanabe | 3b16e9f419 | |
Yu Watanabe | d5a7f3b7d4 | |
Yu Watanabe | f1c16ca6d6 | |
Yu Watanabe | b094398b0f | |
Yu Watanabe | 1ee6570843 | |
Yu Watanabe | b7f051c91d | |
Yu Watanabe | a13ead6814 | |
Yu Watanabe | f901a7b39f | |
Yu Watanabe | 9b01cf0406 | |
Yu Watanabe | d5aae0713d | |
Daan De Meyer | 1d8a81eb4e | |
Daan De Meyer | 86c1317270 | |
Daan De Meyer | f4faac2073 | |
Yu Watanabe | 2bcc2a89f3 | |
Yu Watanabe | 07e6a111c0 | |
Yu Watanabe | c2648f6e23 | |
Daan De Meyer | 1d5b4317cd | |
Yu Watanabe | 8d6eedd8a3 | |
Yu Watanabe | 91eaa90b81 | |
Yu Watanabe | 3b5c5da73a | |
Yu Watanabe | 1775654e2c | |
Yu Watanabe | 0ea6d55a4b | |
Yu Watanabe | 26d35019de | |
Yu Watanabe | b962338104 | |
Yu Watanabe | fae0b00434 | |
Yu Watanabe | f7923ef318 | |
Yu Watanabe | 36df48d863 | |
Yu Watanabe | 53c638db16 | |
Yu Watanabe | 751a247794 | |
Yu Watanabe | 07dbbda0fc | |
Yu Watanabe | ed4a6c476e |
|
@ -962,7 +962,9 @@ default ignore - -</programlisting>
|
||||||
discovered/supported/used, prints <literal>no</literal>. Otherwise prints
|
discovered/supported/used, prints <literal>no</literal>. Otherwise prints
|
||||||
<literal>partial</literal>. In either of these two cases exits with non-zero exit status. It also shows
|
<literal>partial</literal>. In either of these two cases exits with non-zero exit status. It also shows
|
||||||
five lines indicating separately whether firmware, drivers, the system, the kernel and libraries
|
five lines indicating separately whether firmware, drivers, the system, the kernel and libraries
|
||||||
discovered/support/use TPM2.</para>
|
discovered/support/use TPM2. Currently, required libraries are <filename>libtss2-esys.so.0</filename>,
|
||||||
|
<filename>libtss2-rc.so.0</filename>, and <filename>libtss2-mu.so.0</filename>. The requirement may be
|
||||||
|
changed in the future release.</para>
|
||||||
|
|
||||||
<para>Note, this checks for TPM 2.0 devices only, and does not consider TPM 1.2 at all.</para>
|
<para>Note, this checks for TPM 2.0 devices only, and does not consider TPM 1.2 at all.</para>
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Description</title>
|
<title>Description</title>
|
||||||
|
|
||||||
<para><command>systemd-nsresourced</command> is a system service that permits transient delegation of a a
|
<para><command>systemd-nsresourced</command> is a system service that permits transient delegation of a
|
||||||
UID/GID range to a user namespace (see <citerefentry
|
UID/GID range to a user namespace (see <citerefentry
|
||||||
project='man-pages'><refentrytitle>user_namespaces</refentrytitle><manvolnum>7</manvolnum></citerefentry>)
|
project='man-pages'><refentrytitle>user_namespaces</refentrytitle><manvolnum>7</manvolnum></citerefentry>)
|
||||||
allocated by a client, via a Varlink IPC API.</para>
|
allocated by a client, via a Varlink IPC API.</para>
|
||||||
|
|
|
@ -3,18 +3,11 @@
|
||||||
set -e
|
set -e
|
||||||
set -o nounset
|
set -o nounset
|
||||||
|
|
||||||
if [[ "$DISTRIBUTION" =~ ubuntu|debian ]]; then
|
|
||||||
SUDO_GROUP=sudo
|
|
||||||
else
|
|
||||||
SUDO_GROUP=wheel
|
|
||||||
fi
|
|
||||||
|
|
||||||
useradd \
|
useradd \
|
||||||
--uid 4711 \
|
--uid 4711 \
|
||||||
--user-group \
|
--user-group \
|
||||||
--create-home \
|
--create-home \
|
||||||
--password "$(openssl passwd -1 testuser)" \
|
--password "$(openssl passwd -1 testuser)" \
|
||||||
--groups "$SUDO_GROUP",systemd-journal \
|
|
||||||
--shell /bin/bash \
|
--shell /bin/bash \
|
||||||
testuser
|
testuser
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ _systemd_analyze() {
|
||||||
)
|
)
|
||||||
|
|
||||||
local -A VERBS=(
|
local -A VERBS=(
|
||||||
[STANDALONE]='time blame unit-files unit-paths exit-status compare-versions calendar timestamp timespan pcrs srk'
|
[STANDALONE]='time blame unit-files unit-paths exit-status compare-versions calendar timestamp timespan pcrs srk has-tpm2'
|
||||||
[CRITICAL_CHAIN]='critical-chain'
|
[CRITICAL_CHAIN]='critical-chain'
|
||||||
[DOT]='dot'
|
[DOT]='dot'
|
||||||
[DUMP]='dump'
|
[DUMP]='dump'
|
||||||
|
|
|
@ -73,6 +73,7 @@ JSON or table format'
|
||||||
'timespan:Parse a systemd syntax timespan'
|
'timespan:Parse a systemd syntax timespan'
|
||||||
'security:Analyze security settings of a service'
|
'security:Analyze security settings of a service'
|
||||||
'inspect-elf:Parse and print ELF package metadata'
|
'inspect-elf:Parse and print ELF package metadata'
|
||||||
|
'has-tpm2:Report whether TPM2 support is available'
|
||||||
# log-level, log-target, service-watchdogs have been deprecated
|
# log-level, log-target, service-watchdogs have been deprecated
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@ int verb_pcrs(int argc, char *argv[], void *userdata) {
|
||||||
const char *alg = NULL;
|
const char *alg = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (tpm2_support() != TPM2_SUPPORT_FULL)
|
if (!tpm2_is_fully_supported())
|
||||||
log_notice("System lacks full TPM2 support, not showing PCR state.");
|
log_notice("System lacks full TPM2 support, not showing PCR state.");
|
||||||
else {
|
else {
|
||||||
r = get_pcr_alg(&alg);
|
r = get_pcr_alg(&alg);
|
||||||
|
|
|
@ -411,7 +411,6 @@ int verb_status(int argc, char *argv[], void *userdata) {
|
||||||
_cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL, *stub = NULL, *stub_path = NULL,
|
_cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL, *stub = NULL, *stub_path = NULL,
|
||||||
*current_entry = NULL, *oneshot_entry = NULL, *default_entry = NULL;
|
*current_entry = NULL, *oneshot_entry = NULL, *default_entry = NULL;
|
||||||
uint64_t loader_features = 0, stub_features = 0;
|
uint64_t loader_features = 0, stub_features = 0;
|
||||||
Tpm2Support s;
|
|
||||||
int have;
|
int have;
|
||||||
|
|
||||||
(void) efi_get_variable_string_and_warn(EFI_LOADER_VARIABLE(LoaderFirmwareType), &fw_type);
|
(void) efi_get_variable_string_and_warn(EFI_LOADER_VARIABLE(LoaderFirmwareType), &fw_type);
|
||||||
|
@ -440,7 +439,7 @@ int verb_status(int argc, char *argv[], void *userdata) {
|
||||||
else
|
else
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
s = tpm2_support();
|
Tpm2Support s = tpm2_support_full(TPM2_SUPPORT_FIRMWARE|TPM2_SUPPORT_DRIVER);
|
||||||
printf(" TPM2 Support: %s%s%s\n",
|
printf(" TPM2 Support: %s%s%s\n",
|
||||||
FLAGS_SET(s, TPM2_SUPPORT_FIRMWARE|TPM2_SUPPORT_DRIVER) ? ansi_highlight_green() :
|
FLAGS_SET(s, TPM2_SUPPORT_FIRMWARE|TPM2_SUPPORT_DRIVER) ? ansi_highlight_green() :
|
||||||
(s & (TPM2_SUPPORT_FIRMWARE|TPM2_SUPPORT_DRIVER)) != 0 ? ansi_highlight_red() : ansi_highlight_yellow(),
|
(s & (TPM2_SUPPORT_FIRMWARE|TPM2_SUPPORT_DRIVER)) != 0 ? ansi_highlight_red() : ansi_highlight_yellow(),
|
||||||
|
|
|
@ -450,7 +450,7 @@ static size_t pe_section_table_find_profile_length(
|
||||||
assert(start >= section_table);
|
assert(start >= section_table);
|
||||||
assert(start < section_table + n_section_table);
|
assert(start < section_table + n_section_table);
|
||||||
|
|
||||||
/* Look for the next .profile (or the end of the table), this is where the the sections for this
|
/* Look for the next .profile (or the end of the table), this is where the sections for this
|
||||||
* profile end. The base profile does not start with a .profile, the others do, hence conditionally
|
* profile end. The base profile does not start with a .profile, the others do, hence conditionally
|
||||||
* skip over the first entry. */
|
* skip over the first entry. */
|
||||||
const PeSectionHeader *e;
|
const PeSectionHeader *e;
|
||||||
|
@ -485,7 +485,7 @@ EFI_STATUS pe_locate_profile_sections(
|
||||||
if (!p)
|
if (!p)
|
||||||
return EFI_NOT_FOUND;
|
return EFI_NOT_FOUND;
|
||||||
|
|
||||||
/* Look for the next .profile (or the end of the table), this is where the the sections for this
|
/* Look for the next .profile (or the end of the table), this is where the sections for this
|
||||||
* profile end. */
|
* profile end. */
|
||||||
size_t n = pe_section_table_find_profile_length(section_table, n_section_table, p, profile);
|
size_t n = pe_section_table_find_profile_length(section_table, n_section_table, p, profile);
|
||||||
|
|
||||||
|
|
|
@ -1005,7 +1005,7 @@ static int validate_stub(void) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (tpm2_support() != TPM2_SUPPORT_FULL)
|
if (!tpm2_is_fully_supported())
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Sorry, system lacks full TPM2 support.");
|
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Sorry, system lacks full TPM2 support.");
|
||||||
|
|
||||||
r = efi_stub_get_features(&features);
|
r = efi_stub_get_features(&features);
|
||||||
|
|
|
@ -1229,7 +1229,7 @@ static int generic_method_get_interface_description(
|
||||||
sd_varlink_method_flags_t flags,
|
sd_varlink_method_flags_t flags,
|
||||||
void *userdata) {
|
void *userdata) {
|
||||||
|
|
||||||
static const struct sd_json_dispatch_field dispatch_table[] = {
|
static const sd_json_dispatch_field dispatch_table[] = {
|
||||||
{ "interface", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, 0, SD_JSON_MANDATORY },
|
{ "interface", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, 0, SD_JSON_MANDATORY },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
|
@ -416,19 +416,18 @@ static int list_machine_one(sd_varlink *link, Machine *m, bool more) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vl_method_list(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
static int vl_method_list(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||||
Manager *m = ASSERT_PTR(userdata);
|
static const sd_json_dispatch_field dispatch_table[] = {
|
||||||
const char *mn = NULL;
|
{ "name", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, 0, 0 },
|
||||||
|
|
||||||
const sd_json_dispatch_field dispatch_table[] = {
|
|
||||||
{ "name", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, PTR_TO_SIZE(&mn), 0 },
|
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Manager *m = ASSERT_PTR(userdata);
|
||||||
|
const char *mn = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(parameters);
|
assert(parameters);
|
||||||
|
|
||||||
r = sd_varlink_dispatch(link, parameters, dispatch_table, 0);
|
r = sd_varlink_dispatch(link, parameters, dispatch_table, &mn);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|
|
@ -97,8 +97,8 @@ static int neighbor_append_json(Neighbor *n, sd_json_variant **array) {
|
||||||
|
|
||||||
return sd_json_variant_append_arraybo(
|
return sd_json_variant_append_arraybo(
|
||||||
array,
|
array,
|
||||||
SD_JSON_BUILD_PAIR_INTEGER("Family", n->family),
|
SD_JSON_BUILD_PAIR_INTEGER("Family", n->dst_addr.family),
|
||||||
JSON_BUILD_PAIR_IN_ADDR("Destination", &n->in_addr, n->family),
|
JSON_BUILD_PAIR_IN_ADDR("Destination", &n->dst_addr.address, n->dst_addr.family),
|
||||||
JSON_BUILD_PAIR_HW_ADDR("LinkLayerAddress", &n->ll_addr),
|
JSON_BUILD_PAIR_HW_ADDR("LinkLayerAddress", &n->ll_addr),
|
||||||
SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(n->source)),
|
SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(n->source)),
|
||||||
SD_JSON_BUILD_PAIR_STRING("ConfigState", state));
|
SD_JSON_BUILD_PAIR_STRING("ConfigState", state));
|
||||||
|
@ -168,7 +168,7 @@ static int nexthop_append_json(NextHop *n, sd_json_variant **array) {
|
||||||
return sd_json_variant_append_arraybo(
|
return sd_json_variant_append_arraybo(
|
||||||
array,
|
array,
|
||||||
SD_JSON_BUILD_PAIR_UNSIGNED("ID", n->id),
|
SD_JSON_BUILD_PAIR_UNSIGNED("ID", n->id),
|
||||||
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("Gateway", &n->gw, n->family),
|
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("Gateway", &n->gw.address, n->family),
|
||||||
SD_JSON_BUILD_PAIR_UNSIGNED("Flags", n->flags),
|
SD_JSON_BUILD_PAIR_UNSIGNED("Flags", n->flags),
|
||||||
SD_JSON_BUILD_PAIR_STRING("FlagsString", strempty(flags)),
|
SD_JSON_BUILD_PAIR_STRING("FlagsString", strempty(flags)),
|
||||||
SD_JSON_BUILD_PAIR_UNSIGNED("Protocol", n->protocol),
|
SD_JSON_BUILD_PAIR_UNSIGNED("Protocol", n->protocol),
|
||||||
|
|
|
@ -147,29 +147,29 @@ static int neighbor_dup(const Neighbor *neighbor, Neighbor **ret) {
|
||||||
static void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state) {
|
static void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state) {
|
||||||
assert(neighbor);
|
assert(neighbor);
|
||||||
|
|
||||||
siphash24_compress_typesafe(neighbor->family, state);
|
siphash24_compress_typesafe(neighbor->dst_addr.family, state);
|
||||||
|
|
||||||
if (!IN_SET(neighbor->family, AF_INET, AF_INET6))
|
if (!IN_SET(neighbor->dst_addr.family, AF_INET, AF_INET6))
|
||||||
/* treat any other address family as AF_UNSPEC */
|
/* treat any other address family as AF_UNSPEC */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Equality of neighbors are given by the destination address.
|
/* Equality of neighbors are given by the destination address.
|
||||||
* See neigh_lookup() in the kernel. */
|
* See neigh_lookup() in the kernel. */
|
||||||
in_addr_hash_func(&neighbor->in_addr, neighbor->family, state);
|
in_addr_hash_func(&neighbor->dst_addr.address, neighbor->dst_addr.family, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int neighbor_compare_func(const Neighbor *a, const Neighbor *b) {
|
static int neighbor_compare_func(const Neighbor *a, const Neighbor *b) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = CMP(a->family, b->family);
|
r = CMP(a->dst_addr.family, b->dst_addr.family);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (!IN_SET(a->family, AF_INET, AF_INET6))
|
if (!IN_SET(a->dst_addr.family, AF_INET, AF_INET6))
|
||||||
/* treat any other address family as AF_UNSPEC */
|
/* treat any other address family as AF_UNSPEC */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return memcmp(&a->in_addr, &b->in_addr, FAMILY_ADDRESS_SIZE(a->family));
|
return memcmp(&a->dst_addr.address, &b->dst_addr.address, FAMILY_ADDRESS_SIZE(a->dst_addr.family));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int neighbor_get_request(Link *link, const Neighbor *neighbor, Request **ret) {
|
static int neighbor_get_request(Link *link, const Neighbor *neighbor, Request **ret) {
|
||||||
|
@ -244,7 +244,7 @@ static void log_neighbor_debug(const Neighbor *neighbor, const char *str, const
|
||||||
"%s %s neighbor (%s): lladdr: %s, dst: %s",
|
"%s %s neighbor (%s): lladdr: %s, dst: %s",
|
||||||
str, strna(network_config_source_to_string(neighbor->source)), strna(state),
|
str, strna(network_config_source_to_string(neighbor->source)), strna(state),
|
||||||
HW_ADDR_TO_STR(&neighbor->ll_addr),
|
HW_ADDR_TO_STR(&neighbor->ll_addr),
|
||||||
IN_ADDR_TO_STRING(neighbor->family, &neighbor->in_addr));
|
IN_ADDR_TO_STRING(neighbor->dst_addr.family, &neighbor->dst_addr.address));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int neighbor_configure(Neighbor *neighbor, Link *link, Request *req) {
|
static int neighbor_configure(Neighbor *neighbor, Link *link, Request *req) {
|
||||||
|
@ -261,7 +261,7 @@ static int neighbor_configure(Neighbor *neighbor, Link *link, Request *req) {
|
||||||
log_neighbor_debug(neighbor, "Configuring", link);
|
log_neighbor_debug(neighbor, "Configuring", link);
|
||||||
|
|
||||||
r = sd_rtnl_message_new_neigh(link->manager->rtnl, &m, RTM_NEWNEIGH,
|
r = sd_rtnl_message_new_neigh(link->manager->rtnl, &m, RTM_NEWNEIGH,
|
||||||
link->ifindex, neighbor->family);
|
link->ifindex, neighbor->dst_addr.family);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -273,7 +273,7 @@ static int neighbor_configure(Neighbor *neighbor, Link *link, Request *req) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = netlink_message_append_in_addr_union(m, NDA_DST, neighbor->family, &neighbor->in_addr);
|
r = netlink_message_append_in_addr_union(m, NDA_DST, neighbor->dst_addr.family, &neighbor->dst_addr.address);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -338,7 +338,7 @@ static int link_request_neighbor(Link *link, const Neighbor *neighbor) {
|
||||||
"The link layer address length (%zu) for neighbor %s does not match with "
|
"The link layer address length (%zu) for neighbor %s does not match with "
|
||||||
"the hardware address length (%zu), ignoring the setting.",
|
"the hardware address length (%zu), ignoring the setting.",
|
||||||
neighbor->ll_addr.length,
|
neighbor->ll_addr.length,
|
||||||
IN_ADDR_TO_STRING(neighbor->family, &neighbor->in_addr),
|
IN_ADDR_TO_STRING(neighbor->dst_addr.family, &neighbor->dst_addr.address),
|
||||||
link->hw_addr.length);
|
link->hw_addr.length);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -451,11 +451,11 @@ int neighbor_remove(Neighbor *neighbor, Link *link) {
|
||||||
log_neighbor_debug(neighbor, "Removing", link);
|
log_neighbor_debug(neighbor, "Removing", link);
|
||||||
|
|
||||||
r = sd_rtnl_message_new_neigh(link->manager->rtnl, &m, RTM_DELNEIGH,
|
r = sd_rtnl_message_new_neigh(link->manager->rtnl, &m, RTM_DELNEIGH,
|
||||||
link->ifindex, neighbor->family);
|
link->ifindex, neighbor->dst_addr.family);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not allocate RTM_DELNEIGH message: %m");
|
return log_link_error_errno(link, r, "Could not allocate RTM_DELNEIGH message: %m");
|
||||||
|
|
||||||
r = netlink_message_append_in_addr_union(m, NDA_DST, neighbor->family, &neighbor->in_addr);
|
r = netlink_message_append_in_addr_union(m, NDA_DST, neighbor->dst_addr.family, &neighbor->dst_addr.address);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not append NDA_DST attribute: %m");
|
return log_link_error_errno(link, r, "Could not append NDA_DST attribute: %m");
|
||||||
|
|
||||||
|
@ -593,19 +593,19 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message,
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
/* First, retrieve the fundamental information about the neighbor. */
|
/* First, retrieve the fundamental information about the neighbor. */
|
||||||
r = sd_rtnl_message_neigh_get_family(message, &tmp->family);
|
r = sd_rtnl_message_neigh_get_family(message, &tmp->dst_addr.family);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_link_warning(link, "rtnl: received neighbor message without family, ignoring.");
|
log_link_warning(link, "rtnl: received neighbor message without family, ignoring.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (tmp->family == AF_BRIDGE) /* Currently, we do not support it. */
|
if (tmp->dst_addr.family == AF_BRIDGE) /* Currently, we do not support it. */
|
||||||
return 0;
|
return 0;
|
||||||
if (!IN_SET(tmp->family, AF_INET, AF_INET6)) {
|
if (!IN_SET(tmp->dst_addr.family, AF_INET, AF_INET6)) {
|
||||||
log_link_debug(link, "rtnl: received neighbor message with invalid family '%i', ignoring.", tmp->family);
|
log_link_debug(link, "rtnl: received neighbor message with invalid family '%i', ignoring.", tmp->dst_addr.family);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = netlink_message_read_in_addr_union(message, NDA_DST, tmp->family, &tmp->in_addr);
|
r = netlink_message_read_in_addr_union(message, NDA_DST, tmp->dst_addr.family, &tmp->dst_addr.address);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_link_warning_errno(link, r, "rtnl: received neighbor message without valid address, ignoring: %m");
|
log_link_warning_errno(link, r, "rtnl: received neighbor message without valid address, ignoring: %m");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -660,28 +660,28 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define log_neighbor_section(neighbor, fmt, ...) \
|
||||||
|
({ \
|
||||||
|
const Neighbor *_neighbor = (neighbor); \
|
||||||
|
log_section_warning_errno( \
|
||||||
|
_neighbor ? _neighbor->section : NULL, \
|
||||||
|
SYNTHETIC_ERRNO(EINVAL), \
|
||||||
|
fmt " Ignoring [Neighbor] section.", \
|
||||||
|
##__VA_ARGS__); \
|
||||||
|
})
|
||||||
|
|
||||||
static int neighbor_section_verify(Neighbor *neighbor) {
|
static int neighbor_section_verify(Neighbor *neighbor) {
|
||||||
if (section_is_invalid(neighbor->section))
|
if (section_is_invalid(neighbor->section))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (neighbor->family == AF_UNSPEC)
|
if (neighbor->dst_addr.family == AF_UNSPEC)
|
||||||
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_neighbor_section(neighbor, "Neighbor section without Address= configured.");
|
||||||
"%s: Neighbor section without Address= configured. "
|
|
||||||
"Ignoring [Neighbor] section from line %u.",
|
|
||||||
neighbor->section->filename, neighbor->section->line);
|
|
||||||
|
|
||||||
if (neighbor->family == AF_INET6 && !socket_ipv6_is_supported())
|
if (neighbor->dst_addr.family == AF_INET6 && !socket_ipv6_is_supported())
|
||||||
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_neighbor_section(neighbor, "Neighbor section with an IPv6 destination address configured, but the kernel does not support IPv6.");
|
||||||
"%s: Neighbor section with an IPv6 destination address configured, "
|
|
||||||
"but the kernel does not support IPv6. "
|
|
||||||
"Ignoring [Neighbor] section from line %u.",
|
|
||||||
neighbor->section->filename, neighbor->section->line);
|
|
||||||
|
|
||||||
if (neighbor->ll_addr.length == 0)
|
if (neighbor->ll_addr.length == 0)
|
||||||
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_neighbor_section(neighbor, "Neighbor section without LinkLayerAddress= configured.");
|
||||||
"%s: Neighbor section without LinkLayerAddress= configured. "
|
|
||||||
"Ignoring [Neighbor] section from line %u.",
|
|
||||||
neighbor->section->filename, neighbor->section->line);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -709,7 +709,7 @@ int network_drop_invalid_neighbors(Network *network) {
|
||||||
log_warning("%s: Duplicated neighbor settings for %s is specified at line %u and %u, "
|
log_warning("%s: Duplicated neighbor settings for %s is specified at line %u and %u, "
|
||||||
"dropping the neighbor setting specified at line %u.",
|
"dropping the neighbor setting specified at line %u.",
|
||||||
dup->section->filename,
|
dup->section->filename,
|
||||||
IN_ADDR_TO_STRING(neighbor->family, &neighbor->in_addr),
|
IN_ADDR_TO_STRING(neighbor->dst_addr.family, &neighbor->dst_addr.address),
|
||||||
neighbor->section->line,
|
neighbor->section->line,
|
||||||
dup->section->line, dup->section->line);
|
dup->section->line, dup->section->line);
|
||||||
/* neighbor_detach() will drop the neighbor from neighbors_by_section. */
|
/* neighbor_detach() will drop the neighbor from neighbors_by_section. */
|
||||||
|
@ -728,7 +728,7 @@ int network_drop_invalid_neighbors(Network *network) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int config_parse_neighbor_address(
|
int config_parse_neighbor_section(
|
||||||
const char *unit,
|
const char *unit,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
unsigned line,
|
unsigned line,
|
||||||
|
@ -740,76 +740,26 @@ int config_parse_neighbor_address(
|
||||||
void *data,
|
void *data,
|
||||||
void *userdata) {
|
void *userdata) {
|
||||||
|
|
||||||
_cleanup_(neighbor_unref_or_set_invalidp) Neighbor *n = NULL;
|
static const ConfigSectionParser table[_NEIGHBOR_CONF_PARSER_MAX] = {
|
||||||
|
[NEIGHBOR_DESTINATION_ADDRESS] = { .parser = config_parse_in_addr_data, .ltype = 0, .offset = offsetof(Neighbor, dst_addr), },
|
||||||
|
[NEIGHBOR_LINK_LAYER_ADDRESS] = { .parser = config_parse_hw_addr, .ltype = 0, .offset = offsetof(Neighbor, ll_addr), },
|
||||||
|
};
|
||||||
|
|
||||||
|
_cleanup_(neighbor_unref_or_set_invalidp) Neighbor *neighbor = NULL;
|
||||||
Network *network = ASSERT_PTR(userdata);
|
Network *network = ASSERT_PTR(userdata);
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(filename);
|
assert(filename);
|
||||||
assert(section);
|
|
||||||
assert(lvalue);
|
|
||||||
assert(rvalue);
|
|
||||||
|
|
||||||
r = neighbor_new_static(network, filename, section_line, &n);
|
r = neighbor_new_static(network, filename, section_line, &neighbor);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
if (isempty(rvalue)) {
|
r = config_section_parse(table, ELEMENTSOF(table),
|
||||||
n->family = AF_UNSPEC;
|
unit, filename, line, section, section_line, lvalue, ltype, rvalue, neighbor);
|
||||||
n->in_addr = IN_ADDR_NULL;
|
if (r <= 0) /* 0 means non-critical error, but the section will be ignored. */
|
||||||
TAKE_PTR(n);
|
return r;
|
||||||
return 0;
|
|
||||||
}
|
TAKE_PTR(neighbor);
|
||||||
|
|
||||||
r = in_addr_from_string_auto(rvalue, &n->family, &n->in_addr);
|
|
||||||
if (r < 0) {
|
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
|
||||||
"Neighbor Address is invalid, ignoring assignment: %s", rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TAKE_PTR(n);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int config_parse_neighbor_lladdr(
|
|
||||||
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) {
|
|
||||||
|
|
||||||
_cleanup_(neighbor_unref_or_set_invalidp) Neighbor *n = NULL;
|
|
||||||
Network *network = ASSERT_PTR(userdata);
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(filename);
|
|
||||||
assert(section);
|
|
||||||
assert(lvalue);
|
|
||||||
assert(rvalue);
|
|
||||||
|
|
||||||
r = neighbor_new_static(network, filename, section_line, &n);
|
|
||||||
if (r < 0)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
if (isempty(rvalue)) {
|
|
||||||
n->ll_addr = HW_ADDR_NULL;
|
|
||||||
TAKE_PTR(n);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = parse_hw_addr(rvalue, &n->ll_addr);
|
|
||||||
if (r < 0) {
|
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
|
||||||
"Neighbor %s= is invalid, ignoring assignment: %s",
|
|
||||||
lvalue, rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TAKE_PTR(n);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,7 @@ typedef struct Neighbor {
|
||||||
|
|
||||||
unsigned n_ref;
|
unsigned n_ref;
|
||||||
|
|
||||||
int family;
|
struct in_addr_data dst_addr;
|
||||||
union in_addr_union in_addr;
|
|
||||||
struct hw_addr_data ll_addr;
|
struct hw_addr_data ll_addr;
|
||||||
} Neighbor;
|
} Neighbor;
|
||||||
|
|
||||||
|
@ -46,5 +45,11 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message,
|
||||||
|
|
||||||
DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(Neighbor, neighbor);
|
DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(Neighbor, neighbor);
|
||||||
|
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_address);
|
typedef enum NeighborConfParserType {
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_lladdr);
|
NEIGHBOR_DESTINATION_ADDRESS,
|
||||||
|
NEIGHBOR_LINK_LAYER_ADDRESS,
|
||||||
|
_NEIGHBOR_CONF_PARSER_MAX,
|
||||||
|
_NEIGHBOR_CONF_PARSER_INVALID = -EINVAL,
|
||||||
|
} NeighborConfParserType;
|
||||||
|
|
||||||
|
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_section);
|
||||||
|
|
|
@ -173,9 +173,9 @@ Address.NetLabel, config_parse_address_section,
|
||||||
Address.NFTSet, config_parse_address_section, ADDRESS_NFT_SET, 0
|
Address.NFTSet, config_parse_address_section, ADDRESS_NFT_SET, 0
|
||||||
IPv6AddressLabel.Prefix, config_parse_ipv6_address_label_section, IPV6_ADDRESS_LABEL_PREFIX, 0
|
IPv6AddressLabel.Prefix, config_parse_ipv6_address_label_section, IPV6_ADDRESS_LABEL_PREFIX, 0
|
||||||
IPv6AddressLabel.Label, config_parse_ipv6_address_label_section, IPV6_ADDRESS_LABEL, 0
|
IPv6AddressLabel.Label, config_parse_ipv6_address_label_section, IPV6_ADDRESS_LABEL, 0
|
||||||
Neighbor.Address, config_parse_neighbor_address, 0, 0
|
Neighbor.Address, config_parse_neighbor_section, NEIGHBOR_DESTINATION_ADDRESS, 0
|
||||||
Neighbor.LinkLayerAddress, config_parse_neighbor_lladdr, 0, 0
|
Neighbor.LinkLayerAddress, config_parse_neighbor_section, NEIGHBOR_LINK_LAYER_ADDRESS, 0
|
||||||
Neighbor.MACAddress, config_parse_neighbor_lladdr, 0, 0 /* deprecated */
|
Neighbor.MACAddress, config_parse_neighbor_section, NEIGHBOR_LINK_LAYER_ADDRESS, 0 /* deprecated */
|
||||||
RoutingPolicyRule.TypeOfService, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_TOS, 0
|
RoutingPolicyRule.TypeOfService, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_TOS, 0
|
||||||
RoutingPolicyRule.Priority, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_PRIORITY, 0
|
RoutingPolicyRule.Priority, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_PRIORITY, 0
|
||||||
RoutingPolicyRule.GoTo, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_GOTO, 0
|
RoutingPolicyRule.GoTo, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_GOTO, 0
|
||||||
|
@ -219,12 +219,12 @@ Route.QuickAck, config_parse_route_metric_boolean,
|
||||||
Route.TCPCongestionControlAlgorithm, config_parse_route_metric_tcp_congestion, RTAX_CC_ALGO, 0
|
Route.TCPCongestionControlAlgorithm, config_parse_route_metric_tcp_congestion, RTAX_CC_ALGO, 0
|
||||||
Route.FastOpenNoCookie, config_parse_route_metric_boolean, RTAX_FASTOPEN_NO_COOKIE, 0
|
Route.FastOpenNoCookie, config_parse_route_metric_boolean, RTAX_FASTOPEN_NO_COOKIE, 0
|
||||||
Route.TTLPropagate, config_parse_warn_compat, DISABLED_LEGACY, 0
|
Route.TTLPropagate, config_parse_warn_compat, DISABLED_LEGACY, 0
|
||||||
NextHop.Id, config_parse_nexthop_id, 0, 0
|
NextHop.Id, config_parse_nexthop_section, NEXTHOP_ID, 0
|
||||||
NextHop.Gateway, config_parse_nexthop_gateway, 0, 0
|
NextHop.Gateway, config_parse_nexthop_section, NEXTHOP_GATEWAY, 0
|
||||||
NextHop.Family, config_parse_nexthop_family, 0, 0
|
NextHop.Family, config_parse_nexthop_section, NEXTHOP_FAMILY, 0
|
||||||
NextHop.OnLink, config_parse_nexthop_onlink, 0, 0
|
NextHop.OnLink, config_parse_nexthop_section, NEXTHOP_ONLINK, 0
|
||||||
NextHop.Blackhole, config_parse_nexthop_blackhole, 0, 0
|
NextHop.Blackhole, config_parse_nexthop_section, NEXTHOP_BLACKHOLE, 0
|
||||||
NextHop.Group, config_parse_nexthop_group, 0, 0
|
NextHop.Group, config_parse_nexthop_section, NEXTHOP_GROUP, 0
|
||||||
DHCPv4.RequestAddress, config_parse_in_addr_non_null, AF_INET, offsetof(Network, dhcp_request_address)
|
DHCPv4.RequestAddress, config_parse_in_addr_non_null, AF_INET, offsetof(Network, dhcp_request_address)
|
||||||
DHCPv4.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier)
|
DHCPv4.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier)
|
||||||
DHCPv4.UseDNS, config_parse_tristate, 0, offsetof(Network, dhcp_use_dns)
|
DHCPv4.UseDNS, config_parse_tristate, 0, offsetof(Network, dhcp_use_dns)
|
||||||
|
|
|
@ -854,7 +854,7 @@ bool network_has_static_ipv6_configurations(Network *network) {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
ORDERED_HASHMAP_FOREACH(neighbor, network->neighbors_by_section)
|
ORDERED_HASHMAP_FOREACH(neighbor, network->neighbors_by_section)
|
||||||
if (neighbor->family == AF_INET6)
|
if (neighbor->dst_addr.family == AF_INET6)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!hashmap_isempty(network->address_labels_by_section))
|
if (!hashmap_isempty(network->address_labels_by_section))
|
||||||
|
|
|
@ -236,7 +236,7 @@ static int nexthop_compare_full(const NextHop *a, const NextHop *b) {
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (IN_SET(a->family, AF_INET, AF_INET6)) {
|
if (IN_SET(a->family, AF_INET, AF_INET6)) {
|
||||||
r = memcmp(&a->gw, &b->gw, FAMILY_ADDRESS_SIZE(a->family));
|
r = memcmp(&a->gw.address, &b->gw.address, FAMILY_ADDRESS_SIZE(a->family));
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -481,7 +481,7 @@ static void log_nexthop_debug(const NextHop *nexthop, const char *str, Manager *
|
||||||
log_link_debug(link, "%s %s nexthop (%s): id: %"PRIu32", gw: %s, blackhole: %s, group: %s, flags: %s",
|
log_link_debug(link, "%s %s nexthop (%s): id: %"PRIu32", gw: %s, blackhole: %s, group: %s, flags: %s",
|
||||||
str, strna(network_config_source_to_string(nexthop->source)), strna(state),
|
str, strna(network_config_source_to_string(nexthop->source)), strna(state),
|
||||||
nexthop->id,
|
nexthop->id,
|
||||||
IN_ADDR_TO_STRING(nexthop->family, &nexthop->gw),
|
IN_ADDR_TO_STRING(nexthop->family, &nexthop->gw.address),
|
||||||
yes_no(nexthop->blackhole), strna(group), strna(flags));
|
yes_no(nexthop->blackhole), strna(group), strna(flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,8 +627,8 @@ static int nexthop_configure(NextHop *nexthop, Link *link, Request *req) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (in_addr_is_set(nexthop->family, &nexthop->gw)) {
|
if (in_addr_is_set(nexthop->family, &nexthop->gw.address)) {
|
||||||
r = netlink_message_append_in_addr_union(m, NHA_GATEWAY, nexthop->family, &nexthop->gw);
|
r = netlink_message_append_in_addr_union(m, NHA_GATEWAY, nexthop->family, &nexthop->gw.address);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -722,7 +722,7 @@ static bool nexthop_is_ready_to_configure(Link *link, const NextHop *nexthop) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
return gateway_is_ready(link, FLAGS_SET(nexthop->flags, RTNH_F_ONLINK), nexthop->family, &nexthop->gw);
|
return gateway_is_ready(link, FLAGS_SET(nexthop->flags, RTNH_F_ONLINK), nexthop->family, &nexthop->gw.address);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nexthop_process_request(Request *req, Link *link, NextHop *nexthop) {
|
static int nexthop_process_request(Request *req, Link *link, NextHop *nexthop) {
|
||||||
|
@ -1093,9 +1093,9 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message,
|
||||||
(void) nexthop_update_group(nexthop, message);
|
(void) nexthop_update_group(nexthop, message);
|
||||||
|
|
||||||
if (nexthop->family != AF_UNSPEC) {
|
if (nexthop->family != AF_UNSPEC) {
|
||||||
r = netlink_message_read_in_addr_union(message, NHA_GATEWAY, nexthop->family, &nexthop->gw);
|
r = netlink_message_read_in_addr_union(message, NHA_GATEWAY, nexthop->family, &nexthop->gw.address);
|
||||||
if (r == -ENODATA)
|
if (r == -ENODATA)
|
||||||
nexthop->gw = IN_ADDR_NULL;
|
nexthop->gw.address = IN_ADDR_NULL;
|
||||||
else if (r < 0)
|
else if (r < 0)
|
||||||
log_debug_errno(r, "rtnl: could not get NHA_GATEWAY attribute, ignoring: %m");
|
log_debug_errno(r, "rtnl: could not get NHA_GATEWAY attribute, ignoring: %m");
|
||||||
}
|
}
|
||||||
|
@ -1129,66 +1129,60 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define log_nexthop_section(nexthop, fmt, ...) \
|
||||||
|
({ \
|
||||||
|
const NextHop *_nexthop = (nexthop); \
|
||||||
|
log_section_warning_errno( \
|
||||||
|
_nexthop ? _nexthop->section : NULL, \
|
||||||
|
SYNTHETIC_ERRNO(EINVAL), \
|
||||||
|
fmt " Ignoring [NextHop] section.", \
|
||||||
|
##__VA_ARGS__); \
|
||||||
|
})
|
||||||
|
|
||||||
static int nexthop_section_verify(NextHop *nh) {
|
static int nexthop_section_verify(NextHop *nh) {
|
||||||
if (section_is_invalid(nh->section))
|
if (section_is_invalid(nh->section))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!nh->network->manager->manage_foreign_nexthops && nh->id == 0)
|
if (!nh->network->manager->manage_foreign_nexthops && nh->id == 0)
|
||||||
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_nexthop_section(nh, "Nexthop without specifying Id= is not supported if ManageForeignNextHops=no is set in networkd.conf.");
|
||||||
"%s: [NextHop] section without specifying Id= is not supported "
|
|
||||||
"if ManageForeignNextHops=no is set in networkd.conf. "
|
if (nh->family == AF_UNSPEC)
|
||||||
"Ignoring [NextHop] section from line %u.",
|
nh->family = nh->gw.family;
|
||||||
nh->section->filename, nh->section->line);
|
else if (nh->gw.family != AF_UNSPEC && nh->gw.family != nh->family)
|
||||||
|
return log_nexthop_section(nh, "Family= and Gateway= settings for nexthop contradict each other.");
|
||||||
|
|
||||||
|
assert(nh->gw.family == nh->family || nh->gw.family == AF_UNSPEC);
|
||||||
|
|
||||||
if (!hashmap_isempty(nh->group)) {
|
if (!hashmap_isempty(nh->group)) {
|
||||||
if (in_addr_is_set(nh->family, &nh->gw))
|
if (in_addr_is_set(nh->family, &nh->gw.address))
|
||||||
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_nexthop_section(nh, "Nexthop group cannot have gateway address.");
|
||||||
"%s: nexthop group cannot have gateway address. "
|
|
||||||
"Ignoring [NextHop] section from line %u.",
|
|
||||||
nh->section->filename, nh->section->line);
|
|
||||||
|
|
||||||
if (nh->family != AF_UNSPEC)
|
if (nh->family != AF_UNSPEC)
|
||||||
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_nexthop_section(nh, "Nexthop group cannot have Family= setting.");
|
||||||
"%s: nexthop group cannot have Family= setting. "
|
|
||||||
"Ignoring [NextHop] section from line %u.",
|
|
||||||
nh->section->filename, nh->section->line);
|
|
||||||
|
|
||||||
if (nh->blackhole)
|
if (nh->blackhole)
|
||||||
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_nexthop_section(nh, "Nexthop group cannot be a blackhole.");
|
||||||
"%s: nexthop group cannot be a blackhole. "
|
|
||||||
"Ignoring [NextHop] section from line %u.",
|
|
||||||
nh->section->filename, nh->section->line);
|
|
||||||
|
|
||||||
if (nh->onlink > 0)
|
if (nh->onlink > 0)
|
||||||
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_nexthop_section(nh, "Nexthop group cannot have on-link flag.");
|
||||||
"%s: nexthop group cannot have on-link flag. "
|
|
||||||
"Ignoring [NextHop] section from line %u.",
|
|
||||||
nh->section->filename, nh->section->line);
|
|
||||||
} else if (nh->family == AF_UNSPEC)
|
} else if (nh->family == AF_UNSPEC)
|
||||||
/* When neither Family=, Gateway=, nor Group= is specified, assume IPv4. */
|
/* When neither Family=, Gateway=, nor Group= is specified, assume IPv4. */
|
||||||
nh->family = AF_INET;
|
nh->family = AF_INET;
|
||||||
|
|
||||||
if (nh->blackhole) {
|
if (nh->blackhole) {
|
||||||
if (in_addr_is_set(nh->family, &nh->gw))
|
if (in_addr_is_set(nh->family, &nh->gw.address))
|
||||||
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_nexthop_section(nh, "Blackhole nexthop cannot have gateway address.");
|
||||||
"%s: blackhole nexthop cannot have gateway address. "
|
|
||||||
"Ignoring [NextHop] section from line %u.",
|
|
||||||
nh->section->filename, nh->section->line);
|
|
||||||
|
|
||||||
if (nh->onlink > 0)
|
if (nh->onlink > 0)
|
||||||
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_nexthop_section(nh, "Blackhole nexthop cannot have on-link flag.");
|
||||||
"%s: blackhole nexthop cannot have on-link flag. "
|
|
||||||
"Ignoring [NextHop] section from line %u.",
|
|
||||||
nh->section->filename, nh->section->line);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nh->onlink < 0 && in_addr_is_set(nh->family, &nh->gw) &&
|
if (nh->onlink < 0 && in_addr_is_set(nh->family, &nh->gw.address) &&
|
||||||
ordered_hashmap_isempty(nh->network->addresses_by_section)) {
|
ordered_hashmap_isempty(nh->network->addresses_by_section)) {
|
||||||
/* If no address is configured, in most cases the gateway cannot be reachable.
|
/* If no address is configured, in most cases the gateway cannot be reachable.
|
||||||
* TODO: we may need to improve the condition above. */
|
* TODO: we may need to improve the condition above. */
|
||||||
log_warning("%s: Gateway= without static address configured. "
|
log_section_warning(nh->section, "Nexthop with Gateway= specified, but no static address configured. Enabling OnLink= option.");
|
||||||
"Enabling OnLink= option.",
|
|
||||||
nh->section->filename);
|
|
||||||
nh->onlink = true;
|
nh->onlink = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1262,7 +1256,7 @@ int manager_build_nexthop_ids(Manager *manager) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int config_parse_nexthop_id(
|
static int config_parse_nexthop_family(
|
||||||
const char *unit,
|
const char *unit,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
unsigned line,
|
unsigned line,
|
||||||
|
@ -1274,261 +1268,38 @@ int config_parse_nexthop_id(
|
||||||
void *data,
|
void *data,
|
||||||
void *userdata) {
|
void *userdata) {
|
||||||
|
|
||||||
_cleanup_(nexthop_unref_or_set_invalidp) NextHop *n = NULL;
|
int *family = ASSERT_PTR(data);
|
||||||
Network *network = userdata;
|
|
||||||
uint32_t id;
|
if (isempty(rvalue))
|
||||||
|
*family = AF_UNSPEC;
|
||||||
|
else if (streq(rvalue, "ipv4"))
|
||||||
|
*family = AF_INET;
|
||||||
|
else if (streq(rvalue, "ipv6"))
|
||||||
|
*family = AF_INET6;
|
||||||
|
else
|
||||||
|
return log_syntax_parse_error(unit, filename, line, 0, lvalue, rvalue);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int config_parse_nexthop_group(
|
||||||
|
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) {
|
||||||
|
|
||||||
|
Hashmap **group = ASSERT_PTR(data);
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(filename);
|
|
||||||
assert(section);
|
|
||||||
assert(lvalue);
|
|
||||||
assert(rvalue);
|
|
||||||
assert(data);
|
|
||||||
|
|
||||||
r = nexthop_new_static(network, filename, section_line, &n);
|
|
||||||
if (r < 0)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
if (isempty(rvalue)) {
|
if (isempty(rvalue)) {
|
||||||
n->id = 0;
|
*group = hashmap_free_free(*group);
|
||||||
TAKE_PTR(n);
|
return 1;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = safe_atou32(rvalue, &id);
|
|
||||||
if (r < 0) {
|
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
|
||||||
"Could not parse nexthop id \"%s\", ignoring assignment: %m", rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (id == 0) {
|
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
|
||||||
"Invalid nexthop id \"%s\", ignoring assignment: %m", rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
n->id = id;
|
|
||||||
TAKE_PTR(n);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int config_parse_nexthop_gateway(
|
|
||||||
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) {
|
|
||||||
|
|
||||||
_cleanup_(nexthop_unref_or_set_invalidp) NextHop *n = NULL;
|
|
||||||
Network *network = userdata;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(filename);
|
|
||||||
assert(section);
|
|
||||||
assert(lvalue);
|
|
||||||
assert(rvalue);
|
|
||||||
assert(data);
|
|
||||||
|
|
||||||
r = nexthop_new_static(network, filename, section_line, &n);
|
|
||||||
if (r < 0)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
if (isempty(rvalue)) {
|
|
||||||
n->family = AF_UNSPEC;
|
|
||||||
n->gw = IN_ADDR_NULL;
|
|
||||||
|
|
||||||
TAKE_PTR(n);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = in_addr_from_string_auto(rvalue, &n->family, &n->gw);
|
|
||||||
if (r < 0) {
|
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
|
||||||
"Invalid %s='%s', ignoring assignment: %m", lvalue, rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TAKE_PTR(n);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int config_parse_nexthop_family(
|
|
||||||
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) {
|
|
||||||
|
|
||||||
_cleanup_(nexthop_unref_or_set_invalidp) NextHop *n = NULL;
|
|
||||||
Network *network = userdata;
|
|
||||||
AddressFamily a;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(filename);
|
|
||||||
assert(section);
|
|
||||||
assert(lvalue);
|
|
||||||
assert(rvalue);
|
|
||||||
assert(data);
|
|
||||||
|
|
||||||
r = nexthop_new_static(network, filename, section_line, &n);
|
|
||||||
if (r < 0)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
if (isempty(rvalue) &&
|
|
||||||
!in_addr_is_set(n->family, &n->gw)) {
|
|
||||||
/* Accept an empty string only when Gateway= is null or not specified. */
|
|
||||||
n->family = AF_UNSPEC;
|
|
||||||
TAKE_PTR(n);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
a = nexthop_address_family_from_string(rvalue);
|
|
||||||
if (a < 0) {
|
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
|
||||||
"Invalid %s='%s', ignoring assignment: %m", lvalue, rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_addr_is_set(n->family, &n->gw) &&
|
|
||||||
((a == ADDRESS_FAMILY_IPV4 && n->family == AF_INET6) ||
|
|
||||||
(a == ADDRESS_FAMILY_IPV6 && n->family == AF_INET))) {
|
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
|
||||||
"Specified family '%s' conflicts with the family of the previously specified Gateway=, "
|
|
||||||
"ignoring assignment.", rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (a) {
|
|
||||||
case ADDRESS_FAMILY_IPV4:
|
|
||||||
n->family = AF_INET;
|
|
||||||
break;
|
|
||||||
case ADDRESS_FAMILY_IPV6:
|
|
||||||
n->family = AF_INET6;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert_not_reached();
|
|
||||||
}
|
|
||||||
|
|
||||||
TAKE_PTR(n);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int config_parse_nexthop_onlink(
|
|
||||||
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) {
|
|
||||||
|
|
||||||
_cleanup_(nexthop_unref_or_set_invalidp) NextHop *n = NULL;
|
|
||||||
Network *network = userdata;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(filename);
|
|
||||||
assert(section);
|
|
||||||
assert(lvalue);
|
|
||||||
assert(rvalue);
|
|
||||||
assert(data);
|
|
||||||
|
|
||||||
r = nexthop_new_static(network, filename, section_line, &n);
|
|
||||||
if (r < 0)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
r = parse_tristate(rvalue, &n->onlink);
|
|
||||||
if (r < 0) {
|
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
|
||||||
"Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TAKE_PTR(n);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int config_parse_nexthop_blackhole(
|
|
||||||
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) {
|
|
||||||
|
|
||||||
_cleanup_(nexthop_unref_or_set_invalidp) NextHop *n = NULL;
|
|
||||||
Network *network = userdata;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(filename);
|
|
||||||
assert(section);
|
|
||||||
assert(lvalue);
|
|
||||||
assert(rvalue);
|
|
||||||
assert(data);
|
|
||||||
|
|
||||||
r = nexthop_new_static(network, filename, section_line, &n);
|
|
||||||
if (r < 0)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
r = parse_boolean(rvalue);
|
|
||||||
if (r < 0) {
|
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
|
||||||
"Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
n->blackhole = r;
|
|
||||||
|
|
||||||
TAKE_PTR(n);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int config_parse_nexthop_group(
|
|
||||||
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) {
|
|
||||||
|
|
||||||
_cleanup_(nexthop_unref_or_set_invalidp) NextHop *n = NULL;
|
|
||||||
Network *network = userdata;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(filename);
|
|
||||||
assert(section);
|
|
||||||
assert(lvalue);
|
|
||||||
assert(rvalue);
|
|
||||||
assert(data);
|
|
||||||
|
|
||||||
r = nexthop_new_static(network, filename, section_line, &n);
|
|
||||||
if (r < 0)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
if (isempty(rvalue)) {
|
|
||||||
n->group = hashmap_free_free(n->group);
|
|
||||||
TAKE_PTR(n);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const char *p = rvalue;;) {
|
for (const char *p = rvalue;;) {
|
||||||
|
@ -1538,15 +1309,10 @@ int config_parse_nexthop_group(
|
||||||
char *sep;
|
char *sep;
|
||||||
|
|
||||||
r = extract_first_word(&p, &word, NULL, 0);
|
r = extract_first_word(&p, &word, NULL, 0);
|
||||||
if (r == -ENOMEM)
|
if (r < 0)
|
||||||
return log_oom();
|
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
|
||||||
if (r < 0) {
|
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
|
||||||
"Invalid %s=, ignoring assignment: %s", lvalue, rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
break;
|
return 1;
|
||||||
|
|
||||||
nhg = new0(struct nexthop_grp, 1);
|
nhg = new0(struct nexthop_grp, 1);
|
||||||
if (!nhg)
|
if (!nhg)
|
||||||
|
@ -1586,7 +1352,7 @@ int config_parse_nexthop_group(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = hashmap_ensure_put(&n->group, NULL, UINT32_TO_PTR(nhg->id), nhg);
|
r = hashmap_ensure_put(group, NULL, UINT32_TO_PTR(nhg->id), nhg);
|
||||||
if (r == -ENOMEM)
|
if (r == -ENOMEM)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
if (r == -EEXIST) {
|
if (r == -EEXIST) {
|
||||||
|
@ -1598,7 +1364,44 @@ int config_parse_nexthop_group(
|
||||||
assert(r > 0);
|
assert(r > 0);
|
||||||
TAKE_PTR(nhg);
|
TAKE_PTR(nhg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TAKE_PTR(n);
|
int config_parse_nexthop_section(
|
||||||
|
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) {
|
||||||
|
|
||||||
|
static const ConfigSectionParser table[_NEXTHOP_CONF_PARSER_MAX] = {
|
||||||
|
[NEXTHOP_ID] = { .parser = config_parse_uint32, .ltype = 0, .offset = offsetof(NextHop, id), },
|
||||||
|
[NEXTHOP_GATEWAY] = { .parser = config_parse_in_addr_data, .ltype = 0, .offset = offsetof(NextHop, gw), },
|
||||||
|
[NEXTHOP_FAMILY] = { .parser = config_parse_nexthop_family, .ltype = 0, .offset = offsetof(NextHop, family), },
|
||||||
|
[NEXTHOP_ONLINK] = { .parser = config_parse_tristate, .ltype = 0, .offset = offsetof(NextHop, onlink), },
|
||||||
|
[NEXTHOP_BLACKHOLE] = { .parser = config_parse_bool, .ltype = 0, .offset = offsetof(NextHop, blackhole), },
|
||||||
|
[NEXTHOP_GROUP] = { .parser = config_parse_nexthop_group, .ltype = 0, .offset = offsetof(NextHop, group), },
|
||||||
|
};
|
||||||
|
|
||||||
|
_cleanup_(nexthop_unref_or_set_invalidp) NextHop *nexthop = NULL;
|
||||||
|
Network *network = ASSERT_PTR(userdata);
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(filename);
|
||||||
|
|
||||||
|
r = nexthop_new_static(network, filename, section_line, &nexthop);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
r = config_section_parse(table, ELEMENTSOF(table),
|
||||||
|
unit, filename, line, section, section_line, lvalue, ltype, rvalue, nexthop);
|
||||||
|
if (r <= 0) /* 0 means non-critical error, but the section will be ignored. */
|
||||||
|
return r;
|
||||||
|
|
||||||
|
TAKE_PTR(nexthop);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ typedef struct NextHop {
|
||||||
Hashmap *group; /* NHA_GROUP */
|
Hashmap *group; /* NHA_GROUP */
|
||||||
bool blackhole; /* NHA_BLACKHOLE */
|
bool blackhole; /* NHA_BLACKHOLE */
|
||||||
int ifindex; /* NHA_OIF */
|
int ifindex; /* NHA_OIF */
|
||||||
union in_addr_union gw; /* NHA_GATEWAY */
|
struct in_addr_data gw; /* NHA_GATEWAY, gw.family is only used by conf parser. */
|
||||||
|
|
||||||
/* Only used in conf parser and nexthop_section_verify(). */
|
/* Only used in conf parser and nexthop_section_verify(). */
|
||||||
int onlink;
|
int onlink;
|
||||||
|
@ -71,9 +71,15 @@ int manager_build_nexthop_ids(Manager *manager);
|
||||||
|
|
||||||
DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(NextHop, nexthop);
|
DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(NextHop, nexthop);
|
||||||
|
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_id);
|
typedef enum NextHopConfParserType {
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_gateway);
|
NEXTHOP_ID,
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_family);
|
NEXTHOP_GATEWAY,
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_onlink);
|
NEXTHOP_FAMILY,
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_blackhole);
|
NEXTHOP_ONLINK,
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_group);
|
NEXTHOP_BLACKHOLE,
|
||||||
|
NEXTHOP_GROUP,
|
||||||
|
_NEXTHOP_CONF_PARSER_MAX,
|
||||||
|
_NEXTHOP_CONF_PARSER_INVALID = -EINVAL,
|
||||||
|
} NextHopConfParserType;
|
||||||
|
|
||||||
|
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_section);
|
||||||
|
|
|
@ -1742,7 +1742,7 @@ static int oci_seccomp_args(const char *name, sd_json_variant *v, sd_json_dispat
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
JSON_VARIANT_ARRAY_FOREACH(e, v) {
|
JSON_VARIANT_ARRAY_FOREACH(e, v) {
|
||||||
static const struct sd_json_dispatch_field table[] = {
|
static const sd_json_dispatch_field table[] = {
|
||||||
{ "index", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint32, offsetof(struct scmp_arg_cmp, arg), SD_JSON_MANDATORY },
|
{ "index", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint32, offsetof(struct scmp_arg_cmp, arg), SD_JSON_MANDATORY },
|
||||||
{ "value", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint64, offsetof(struct scmp_arg_cmp, datum_a), SD_JSON_MANDATORY },
|
{ "value", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint64, offsetof(struct scmp_arg_cmp, datum_a), SD_JSON_MANDATORY },
|
||||||
{ "valueTwo", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint64, offsetof(struct scmp_arg_cmp, datum_b), 0 },
|
{ "valueTwo", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint64, offsetof(struct scmp_arg_cmp, datum_b), 0 },
|
||||||
|
|
|
@ -369,7 +369,7 @@ static int run(int argc, char *argv[]) {
|
||||||
event = TPM2_EVENT_PHASE;
|
event = TPM2_EVENT_PHASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg_graceful && tpm2_support() != TPM2_SUPPORT_FULL) {
|
if (arg_graceful && !tpm2_is_fully_supported()) {
|
||||||
log_notice("No complete TPM2 support detected, exiting gracefully.");
|
log_notice("No complete TPM2 support detected, exiting gracefully.");
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2876,55 +2876,76 @@ static int print_answer(sd_json_variant *answer) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct MonitorQueryParams {
|
||||||
|
sd_json_variant *question;
|
||||||
|
sd_json_variant *answer;
|
||||||
|
sd_json_variant *collected_questions;
|
||||||
|
int rcode;
|
||||||
|
int error;
|
||||||
|
int ede_code;
|
||||||
|
const char *state;
|
||||||
|
const char *result;
|
||||||
|
const char *ede_msg;
|
||||||
|
} MonitorQueryParams;
|
||||||
|
|
||||||
|
static void monitor_query_params_done(MonitorQueryParams *p) {
|
||||||
|
assert(p);
|
||||||
|
|
||||||
|
sd_json_variant_unref(p->question);
|
||||||
|
sd_json_variant_unref(p->answer);
|
||||||
|
sd_json_variant_unref(p->collected_questions);
|
||||||
|
}
|
||||||
|
|
||||||
static void monitor_query_dump(sd_json_variant *v) {
|
static void monitor_query_dump(sd_json_variant *v) {
|
||||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *question = NULL, *answer = NULL, *collected_questions = NULL;
|
static const sd_json_dispatch_field dispatch_table[] = {
|
||||||
int rcode = -1, error = 0, ede_code = -1;
|
{ "question", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_variant, offsetof(MonitorQueryParams, question), SD_JSON_MANDATORY },
|
||||||
const char *state = NULL, *result = NULL, *ede_msg = NULL;
|
{ "answer", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_variant, offsetof(MonitorQueryParams, answer), 0 },
|
||||||
|
{ "collectedQuestions", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_variant, offsetof(MonitorQueryParams, collected_questions), 0 },
|
||||||
assert(v);
|
{ "state", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(MonitorQueryParams, state), SD_JSON_MANDATORY },
|
||||||
|
{ "result", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(MonitorQueryParams, result), 0 },
|
||||||
sd_json_dispatch_field dispatch_table[] = {
|
{ "rcode", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int, offsetof(MonitorQueryParams, rcode), 0 },
|
||||||
{ "question", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_variant, PTR_TO_SIZE(&question), SD_JSON_MANDATORY },
|
{ "errno", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int, offsetof(MonitorQueryParams, error), 0 },
|
||||||
{ "answer", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_variant, PTR_TO_SIZE(&answer), 0 },
|
{ "extendedDNSErrorCode", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int, offsetof(MonitorQueryParams, ede_code), 0 },
|
||||||
{ "collectedQuestions", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_variant, PTR_TO_SIZE(&collected_questions), 0 },
|
{ "extendedDNSErrorMessage", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(MonitorQueryParams, ede_msg), 0 },
|
||||||
{ "state", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, PTR_TO_SIZE(&state), SD_JSON_MANDATORY },
|
|
||||||
{ "result", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, PTR_TO_SIZE(&result), 0 },
|
|
||||||
{ "rcode", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int, PTR_TO_SIZE(&rcode), 0 },
|
|
||||||
{ "errno", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int, PTR_TO_SIZE(&error), 0 },
|
|
||||||
{ "extendedDNSErrorCode", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int, PTR_TO_SIZE(&ede_code), 0 },
|
|
||||||
{ "extendedDNSErrorMessage", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, PTR_TO_SIZE(&ede_msg), 0 },
|
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (sd_json_dispatch(v, dispatch_table, SD_JSON_LOG|SD_JSON_ALLOW_EXTENSIONS, NULL) < 0)
|
_cleanup_(monitor_query_params_done) MonitorQueryParams p = {
|
||||||
|
.rcode = -1,
|
||||||
|
.ede_code = -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
assert(v);
|
||||||
|
|
||||||
|
if (sd_json_dispatch(v, dispatch_table, SD_JSON_LOG|SD_JSON_ALLOW_EXTENSIONS, &p) < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* First show the current question */
|
/* First show the current question */
|
||||||
print_question('Q', ansi_highlight_cyan(), question);
|
print_question('Q', ansi_highlight_cyan(), p.question);
|
||||||
|
|
||||||
/* And then show the questions that led to this one in case this was a CNAME chain */
|
/* And then show the questions that led to this one in case this was a CNAME chain */
|
||||||
print_question('C', ansi_highlight_grey(), collected_questions);
|
print_question('C', ansi_highlight_grey(), p.collected_questions);
|
||||||
|
|
||||||
printf("%s%s S%s: %s",
|
printf("%s%s S%s: %s",
|
||||||
streq_ptr(state, "success") ? ansi_highlight_green() : ansi_highlight_red(),
|
streq_ptr(p.state, "success") ? ansi_highlight_green() : ansi_highlight_red(),
|
||||||
special_glyph(SPECIAL_GLYPH_ARROW_LEFT),
|
special_glyph(SPECIAL_GLYPH_ARROW_LEFT),
|
||||||
ansi_normal(),
|
ansi_normal(),
|
||||||
strna(streq_ptr(state, "errno") ? errno_to_name(error) :
|
strna(streq_ptr(p.state, "errno") ? errno_to_name(p.error) :
|
||||||
streq_ptr(state, "rcode-failure") ? dns_rcode_to_string(rcode) :
|
streq_ptr(p.state, "rcode-failure") ? dns_rcode_to_string(p.rcode) :
|
||||||
state));
|
p.state));
|
||||||
|
|
||||||
if (!isempty(result))
|
if (!isempty(p.result))
|
||||||
printf(": %s", result);
|
printf(": %s", p.result);
|
||||||
|
|
||||||
if (ede_code >= 0)
|
if (p.ede_code >= 0)
|
||||||
printf(" (%s%s%s)",
|
printf(" (%s%s%s)",
|
||||||
FORMAT_DNS_EDE_RCODE(ede_code),
|
FORMAT_DNS_EDE_RCODE(p.ede_code),
|
||||||
!isempty(ede_msg) ? ": " : "",
|
!isempty(p.ede_msg) ? ": " : "",
|
||||||
strempty(ede_msg));
|
strempty(p.ede_msg));
|
||||||
|
|
||||||
puts("");
|
puts("");
|
||||||
|
|
||||||
print_answer(answer);
|
print_answer(p.answer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int monitor_reply(
|
static int monitor_reply(
|
||||||
|
|
|
@ -2145,26 +2145,31 @@ int dns_resource_key_to_json(DnsResourceKey *key, sd_json_variant **ret) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int dns_resource_key_from_json(sd_json_variant *v, DnsResourceKey **ret) {
|
int dns_resource_key_from_json(sd_json_variant *v, DnsResourceKey **ret) {
|
||||||
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
|
struct params {
|
||||||
uint16_t type = 0, class = 0;
|
uint16_t type;
|
||||||
const char *name = NULL;
|
uint16_t class;
|
||||||
int r;
|
const char *name;
|
||||||
|
};
|
||||||
|
|
||||||
sd_json_dispatch_field dispatch_table[] = {
|
static const sd_json_dispatch_field dispatch_table[] = {
|
||||||
{ "class", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint16, PTR_TO_SIZE(&class), SD_JSON_MANDATORY },
|
{ "class", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint16, offsetof(struct params, class), SD_JSON_MANDATORY },
|
||||||
{ "type", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint16, PTR_TO_SIZE(&type), SD_JSON_MANDATORY },
|
{ "type", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint16, offsetof(struct params, type), SD_JSON_MANDATORY },
|
||||||
{ "name", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, PTR_TO_SIZE(&name), SD_JSON_MANDATORY },
|
{ "name", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(struct params, name), SD_JSON_MANDATORY },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
|
||||||
|
struct params p;
|
||||||
|
int r;
|
||||||
|
|
||||||
assert(v);
|
assert(v);
|
||||||
assert(ret);
|
assert(ret);
|
||||||
|
|
||||||
r = sd_json_dispatch(v, dispatch_table, 0, NULL);
|
r = sd_json_dispatch(v, dispatch_table, 0, &p);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
key = dns_resource_key_new(class, type, name);
|
key = dns_resource_key_new(p.class, p.type, p.name);
|
||||||
if (!key)
|
if (!key)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
|
|
@ -667,7 +667,7 @@ static int has_tpm2(void) {
|
||||||
*
|
*
|
||||||
* Note that we don't check if we ourselves are built with TPM2 support here! */
|
* Note that we don't check if we ourselves are built with TPM2 support here! */
|
||||||
|
|
||||||
return FLAGS_SET(tpm2_support(), TPM2_SUPPORT_SUBSYSTEM|TPM2_SUPPORT_FIRMWARE);
|
return FLAGS_SET(tpm2_support_full(TPM2_SUPPORT_SUBSYSTEM|TPM2_SUPPORT_FIRMWARE), TPM2_SUPPORT_SUBSYSTEM|TPM2_SUPPORT_FIRMWARE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int condition_test_security(Condition *c, char **env) {
|
static int condition_test_security(Condition *c, char **env) {
|
||||||
|
|
|
@ -1764,7 +1764,7 @@ int config_parse_hw_addr(
|
||||||
void *data,
|
void *data,
|
||||||
void *userdata) {
|
void *userdata) {
|
||||||
|
|
||||||
struct hw_addr_data a, *hwaddr = ASSERT_PTR(data);
|
struct hw_addr_data *hwaddr = ASSERT_PTR(data);
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(filename);
|
assert(filename);
|
||||||
|
@ -1776,11 +1776,10 @@ int config_parse_hw_addr(
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = parse_hw_addr_full(rvalue, ltype, &a);
|
r = parse_hw_addr_full(rvalue, ltype, hwaddr);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
|
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
|
||||||
|
|
||||||
*hwaddr = a;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1973,6 +1972,36 @@ int config_parse_in_addr_non_null(
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int config_parse_in_addr_data(
|
||||||
|
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) {
|
||||||
|
|
||||||
|
struct in_addr_data *p = ASSERT_PTR(data);
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(filename);
|
||||||
|
assert(lvalue);
|
||||||
|
|
||||||
|
if (isempty(rvalue)) {
|
||||||
|
*p = (struct in_addr_data) {};
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = in_addr_from_string_auto(rvalue, &p->family, &p->address);
|
||||||
|
if (r < 0)
|
||||||
|
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int config_parse_unsigned_bounded(
|
int config_parse_unsigned_bounded(
|
||||||
const char *unit,
|
const char *unit,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
|
|
|
@ -304,6 +304,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_hw_addrs);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_ether_addr);
|
CONFIG_PARSER_PROTOTYPE(config_parse_ether_addr);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_ether_addrs);
|
CONFIG_PARSER_PROTOTYPE(config_parse_ether_addrs);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_in_addr_non_null);
|
CONFIG_PARSER_PROTOTYPE(config_parse_in_addr_non_null);
|
||||||
|
CONFIG_PARSER_PROTOTYPE(config_parse_in_addr_data);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_percent);
|
CONFIG_PARSER_PROTOTYPE(config_parse_percent);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_permyriad);
|
CONFIG_PARSER_PROTOTYPE(config_parse_permyriad);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_pid);
|
CONFIG_PARSER_PROTOTYPE(config_parse_pid);
|
||||||
|
|
|
@ -886,7 +886,7 @@ int encrypt_credential_and_warn(
|
||||||
* container tpm2_support will detect this, and will return a different flag combination of
|
* container tpm2_support will detect this, and will return a different flag combination of
|
||||||
* TPM2_SUPPORT_FULL, effectively skipping the use of TPM2 when inside one. */
|
* TPM2_SUPPORT_FULL, effectively skipping the use of TPM2 when inside one. */
|
||||||
|
|
||||||
try_tpm2 = tpm2_support() == TPM2_SUPPORT_FULL;
|
try_tpm2 = tpm2_is_fully_supported();
|
||||||
if (!try_tpm2)
|
if (!try_tpm2)
|
||||||
log_debug("System lacks TPM2 support or running in a container, not attempting to use TPM2.");
|
log_debug("System lacks TPM2 support or running in a container, not attempting to use TPM2.");
|
||||||
} else
|
} else
|
||||||
|
@ -1582,14 +1582,12 @@ int ipc_encrypt_credential(const char *name, usec_t timestamp, usec_t not_after,
|
||||||
return log_error_errno(sd_varlink_error_to_errno(error_id, reply), "Failed to encrypt: %s", error_id);
|
return log_error_errno(sd_varlink_error_to_errno(error_id, reply), "Failed to encrypt: %s", error_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_json_dispatch(
|
static const sd_json_dispatch_field dispatch_table[] = {
|
||||||
reply,
|
{ "blob", SD_JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, 0, SD_JSON_MANDATORY },
|
||||||
(const sd_json_dispatch_field[]) {
|
|
||||||
{ "blob", SD_JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, PTR_TO_SIZE(ret), SD_JSON_MANDATORY },
|
|
||||||
{},
|
{},
|
||||||
},
|
};
|
||||||
SD_JSON_LOG|SD_JSON_ALLOW_EXTENSIONS,
|
|
||||||
/* userdata= */ NULL);
|
r = sd_json_dispatch(reply, dispatch_table, SD_JSON_LOG|SD_JSON_ALLOW_EXTENSIONS, ret);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -1649,14 +1647,12 @@ int ipc_decrypt_credential(const char *validate_name, usec_t validate_timestamp,
|
||||||
return log_error_errno(sd_varlink_error_to_errno(error_id, reply), "Failed to decrypt: %s", error_id);
|
return log_error_errno(sd_varlink_error_to_errno(error_id, reply), "Failed to decrypt: %s", error_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_json_dispatch(
|
static const sd_json_dispatch_field dispatch_table[] = {
|
||||||
reply,
|
{ "data", SD_JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, 0, SD_JSON_MANDATORY },
|
||||||
(const sd_json_dispatch_field[]) {
|
|
||||||
{ "data", SD_JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, PTR_TO_SIZE(ret), SD_JSON_MANDATORY },
|
|
||||||
{},
|
{},
|
||||||
},
|
};
|
||||||
SD_JSON_LOG|SD_JSON_ALLOW_EXTENSIONS,
|
|
||||||
/* userdata= */ NULL);
|
r = sd_json_dispatch(reply, dispatch_table, SD_JSON_LOG|SD_JSON_ALLOW_EXTENSIONS, ret);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|
|
@ -250,6 +250,18 @@ int nsresource_add_cgroup(int userns_fd, int cgroup_fd) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct InterfaceParams {
|
||||||
|
char *host_interface_name;
|
||||||
|
char *namespace_interface_name;
|
||||||
|
} InterfaceParams;
|
||||||
|
|
||||||
|
static void interface_params_done(InterfaceParams *p) {
|
||||||
|
assert(p);
|
||||||
|
|
||||||
|
free(p->host_interface_name);
|
||||||
|
free(p->namespace_interface_name);
|
||||||
|
}
|
||||||
|
|
||||||
int nsresource_add_netif(
|
int nsresource_add_netif(
|
||||||
int userns_fd,
|
int userns_fd,
|
||||||
int netns_fd,
|
int netns_fd,
|
||||||
|
@ -313,20 +325,20 @@ int nsresource_add_netif(
|
||||||
if (error_id)
|
if (error_id)
|
||||||
return log_debug_errno(sd_varlink_error_to_errno(error_id, reply), "Failed to add network to user namespace: %s", error_id);
|
return log_debug_errno(sd_varlink_error_to_errno(error_id, reply), "Failed to add network to user namespace: %s", error_id);
|
||||||
|
|
||||||
_cleanup_free_ char *host_interface_name = NULL, *namespace_interface_name = NULL;
|
static const sd_json_dispatch_field dispatch_table[] = {
|
||||||
r = sd_json_dispatch(
|
{ "hostInterfaceName", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(InterfaceParams, host_interface_name), 0 },
|
||||||
reply,
|
{ "namespaceInterfaceName", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(InterfaceParams, namespace_interface_name), 0 },
|
||||||
(const sd_json_dispatch_field[]) {
|
};
|
||||||
{ "hostInterfaceName", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, PTR_TO_SIZE(&host_interface_name) },
|
|
||||||
{ "namespaceInterfaceName", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, PTR_TO_SIZE(&namespace_interface_name) },
|
_cleanup_(interface_params_done) InterfaceParams p = {};
|
||||||
},
|
r = sd_json_dispatch(reply, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, &p);
|
||||||
SD_JSON_ALLOW_EXTENSIONS,
|
if (r < 0)
|
||||||
/* userdata= */ NULL);
|
return r;
|
||||||
|
|
||||||
if (ret_host_ifname)
|
if (ret_host_ifname)
|
||||||
*ret_host_ifname = TAKE_PTR(host_interface_name);
|
*ret_host_ifname = TAKE_PTR(p.host_interface_name);
|
||||||
if (ret_namespace_ifname)
|
if (ret_namespace_ifname)
|
||||||
*ret_namespace_ifname = TAKE_PTR(namespace_interface_name);
|
*ret_namespace_ifname = TAKE_PTR(p.namespace_interface_name);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -281,6 +281,44 @@ static inline int run_test_table(void) {
|
||||||
} \
|
} \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
#define ASSERT_OK_ZERO_ERRNO(expr) \
|
||||||
|
({ \
|
||||||
|
typeof(expr) _result = (expr); \
|
||||||
|
if (_result < 0) { \
|
||||||
|
log_error_errno(errno, "%s:%i: Assertion failed: expected \"%s\" to succeed but got the following error: %m", \
|
||||||
|
PROJECT_FILE, __LINE__, #expr); \
|
||||||
|
abort(); \
|
||||||
|
} \
|
||||||
|
if (_result != 0) { \
|
||||||
|
char _sexpr[DECIMAL_STR_MAX(typeof(expr))]; \
|
||||||
|
xsprintf(_sexpr, DECIMAL_STR_FMT(_result), _result); \
|
||||||
|
log_error("%s:%i: Assertion failed: expected \"%s\" to be zero, but it is %s.", \
|
||||||
|
PROJECT_FILE, __LINE__, #expr, _sexpr); \
|
||||||
|
abort(); \
|
||||||
|
} \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define ASSERT_OK_EQ_ERRNO(expr1, expr2) \
|
||||||
|
({ \
|
||||||
|
typeof(expr1) _expr1 = (expr1); \
|
||||||
|
typeof(expr2) _expr2 = (expr2); \
|
||||||
|
if (_expr1 < 0) { \
|
||||||
|
log_error_errno(errno, "%s:%i: Assertion failed: expected \"%s\" to succeed but got the following error: %m", \
|
||||||
|
PROJECT_FILE, __LINE__, #expr1); \
|
||||||
|
abort(); \
|
||||||
|
} \
|
||||||
|
if (_expr1 != _expr2) { \
|
||||||
|
char _sexpr1[DECIMAL_STR_MAX(typeof(expr1))]; \
|
||||||
|
char _sexpr2[DECIMAL_STR_MAX(typeof(expr2))]; \
|
||||||
|
xsprintf(_sexpr1, DECIMAL_STR_FMT(_expr1), _expr1); \
|
||||||
|
xsprintf(_sexpr2, DECIMAL_STR_FMT(_expr2), _expr2); \
|
||||||
|
log_error("%s:%i: Assertion failed: expected \"%s == %s\", but %s != %s", \
|
||||||
|
PROJECT_FILE, __LINE__, #expr1, #expr2, _sexpr1, _sexpr2); \
|
||||||
|
abort(); \
|
||||||
|
} \
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
#define ASSERT_FAIL(expr) \
|
#define ASSERT_FAIL(expr) \
|
||||||
({ \
|
({ \
|
||||||
typeof(expr) _result = (expr); \
|
typeof(expr) _result = (expr); \
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
|
#include "ansi-color.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "creds-util.h"
|
#include "creds-util.h"
|
||||||
#include "cryptsetup-util.h"
|
#include "cryptsetup-util.h"
|
||||||
|
@ -7872,11 +7873,11 @@ int tpm2_sym_mode_from_string(const char *mode) {
|
||||||
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown symmetric mode name '%s'", mode);
|
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown symmetric mode name '%s'", mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
Tpm2Support tpm2_support(void) {
|
Tpm2Support tpm2_support_full(Tpm2Support mask) {
|
||||||
Tpm2Support support = TPM2_SUPPORT_NONE;
|
Tpm2Support support = TPM2_SUPPORT_NONE;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (detect_container() <= 0) {
|
if (((mask & (TPM2_SUPPORT_SUBSYSTEM|TPM2_SUPPORT_DRIVER)) != 0) && detect_container() <= 0) {
|
||||||
/* Check if there's a /dev/tpmrm* device via sysfs. If we run in a container we likely just
|
/* Check if there's a /dev/tpmrm* device via sysfs. If we run in a container we likely just
|
||||||
* got the host sysfs mounted. Since devices are generally not virtualized for containers,
|
* got the host sysfs mounted. Since devices are generally not virtualized for containers,
|
||||||
* let's assume containers never have a TPM, at least for now. */
|
* let's assume containers never have a TPM, at least for now. */
|
||||||
|
@ -7893,18 +7894,24 @@ Tpm2Support tpm2_support(void) {
|
||||||
support |= TPM2_SUPPORT_SUBSYSTEM;
|
support |= TPM2_SUPPORT_SUBSYSTEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (efi_has_tpm2())
|
if (FLAGS_SET(mask, TPM2_SUPPORT_FIRMWARE) && efi_has_tpm2())
|
||||||
support |= TPM2_SUPPORT_FIRMWARE;
|
support |= TPM2_SUPPORT_FIRMWARE;
|
||||||
|
|
||||||
#if HAVE_TPM2
|
#if HAVE_TPM2
|
||||||
support |= TPM2_SUPPORT_SYSTEM;
|
support |= TPM2_SUPPORT_SYSTEM;
|
||||||
|
|
||||||
|
if (FLAGS_SET(mask, TPM2_SUPPORT_LIBRARIES)) {
|
||||||
r = dlopen_tpm2();
|
r = dlopen_tpm2();
|
||||||
if (r >= 0)
|
if (r >= 0)
|
||||||
support |= TPM2_SUPPORT_LIBRARIES;
|
support |= TPM2_SUPPORT_LIBRARIES;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return support;
|
return support & mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_field(const char *s, bool supported) {
|
||||||
|
printf("%s%s%s%s\n", supported ? ansi_green() : ansi_red(), plus_minus(supported), s, ansi_normal());
|
||||||
}
|
}
|
||||||
|
|
||||||
int verb_has_tpm2_generic(bool quiet) {
|
int verb_has_tpm2_generic(bool quiet) {
|
||||||
|
@ -7914,22 +7921,17 @@ int verb_has_tpm2_generic(bool quiet) {
|
||||||
|
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
if (s == TPM2_SUPPORT_FULL)
|
if (s == TPM2_SUPPORT_FULL)
|
||||||
puts("yes");
|
printf("%syes%s\n", ansi_green(), ansi_normal());
|
||||||
else if (s == TPM2_SUPPORT_NONE)
|
else if (s == TPM2_SUPPORT_NONE)
|
||||||
puts("no");
|
printf("%sno%s\n", ansi_red(), ansi_normal());
|
||||||
else
|
else
|
||||||
puts("partial");
|
printf("%spartial%s\n", ansi_yellow(), ansi_normal());
|
||||||
|
|
||||||
printf("%sfirmware\n"
|
print_field("firmware", FLAGS_SET(s, TPM2_SUPPORT_FIRMWARE));
|
||||||
"%sdriver\n"
|
print_field("driver", FLAGS_SET(s, TPM2_SUPPORT_DRIVER));
|
||||||
"%ssystem\n"
|
print_field("system", FLAGS_SET(s, TPM2_SUPPORT_SYSTEM));
|
||||||
"%ssubsystem\n"
|
print_field("subsystem", FLAGS_SET(s, TPM2_SUPPORT_SUBSYSTEM));
|
||||||
"%slibraries\n",
|
print_field("libraries", FLAGS_SET(s, TPM2_SUPPORT_LIBRARIES));
|
||||||
plus_minus(s & TPM2_SUPPORT_FIRMWARE),
|
|
||||||
plus_minus(s & TPM2_SUPPORT_DRIVER),
|
|
||||||
plus_minus(s & TPM2_SUPPORT_SYSTEM),
|
|
||||||
plus_minus(s & TPM2_SUPPORT_SUBSYSTEM),
|
|
||||||
plus_minus(s & TPM2_SUPPORT_LIBRARIES));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return inverted bit flags. So that TPM2_SUPPORT_FULL becomes EXIT_SUCCESS and the other values
|
/* Return inverted bit flags. So that TPM2_SUPPORT_FULL becomes EXIT_SUCCESS and the other values
|
||||||
|
|
|
@ -450,8 +450,8 @@ typedef struct {
|
||||||
} systemd_tpm2_plugin_params;
|
} systemd_tpm2_plugin_params;
|
||||||
|
|
||||||
typedef enum Tpm2Support {
|
typedef enum Tpm2Support {
|
||||||
/* NOTE! The systemd-creds tool returns these flags 1:1 as exit status. Hence these flags are pretty
|
/* NOTE! The systemd-analyze has-tpm2 command returns these flags 1:1 as exit status. Hence these
|
||||||
* much ABI! Hence, be extra careful when changing/extending these definitions. */
|
* flags are pretty much ABI! Hence, be extra careful when changing/extending these definitions. */
|
||||||
TPM2_SUPPORT_NONE = 0, /* no support */
|
TPM2_SUPPORT_NONE = 0, /* no support */
|
||||||
TPM2_SUPPORT_FIRMWARE = 1 << 0, /* firmware reports TPM2 was used */
|
TPM2_SUPPORT_FIRMWARE = 1 << 0, /* firmware reports TPM2 was used */
|
||||||
TPM2_SUPPORT_DRIVER = 1 << 1, /* the kernel has a driver loaded for it */
|
TPM2_SUPPORT_DRIVER = 1 << 1, /* the kernel has a driver loaded for it */
|
||||||
|
@ -461,7 +461,13 @@ typedef enum Tpm2Support {
|
||||||
TPM2_SUPPORT_FULL = TPM2_SUPPORT_FIRMWARE|TPM2_SUPPORT_DRIVER|TPM2_SUPPORT_SYSTEM|TPM2_SUPPORT_SUBSYSTEM|TPM2_SUPPORT_LIBRARIES,
|
TPM2_SUPPORT_FULL = TPM2_SUPPORT_FIRMWARE|TPM2_SUPPORT_DRIVER|TPM2_SUPPORT_SYSTEM|TPM2_SUPPORT_SUBSYSTEM|TPM2_SUPPORT_LIBRARIES,
|
||||||
} Tpm2Support;
|
} Tpm2Support;
|
||||||
|
|
||||||
Tpm2Support tpm2_support(void);
|
Tpm2Support tpm2_support_full(Tpm2Support mask);
|
||||||
|
static inline Tpm2Support tpm2_support(void) {
|
||||||
|
return tpm2_support_full(TPM2_SUPPORT_FULL);
|
||||||
|
}
|
||||||
|
static inline bool tpm2_is_fully_supported(void) {
|
||||||
|
return tpm2_support() == TPM2_SUPPORT_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
int verb_has_tpm2_generic(bool quiet);
|
int verb_has_tpm2_generic(bool quiet);
|
||||||
|
|
||||||
|
|
|
@ -161,12 +161,12 @@ static int process_machine(const char *machine, const char *port) {
|
||||||
|
|
||||||
uint32_t cid = VMADDR_CID_ANY;
|
uint32_t cid = VMADDR_CID_ANY;
|
||||||
|
|
||||||
const sd_json_dispatch_field dispatch_table[] = {
|
static const sd_json_dispatch_field dispatch_table[] = {
|
||||||
{ "vSockCid", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint32, PTR_TO_SIZE(&cid), 0 },
|
{ "vSockCid", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint32, 0, 0 },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
r = sd_json_dispatch(result, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, NULL);
|
r = sd_json_dispatch(result, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, &cid);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to parse Varlink reply: %m");
|
return log_error_errno(r, "Failed to parse Varlink reply: %m");
|
||||||
|
|
||||||
|
|
|
@ -321,12 +321,27 @@ static int list_targets(sd_bus *bus) {
|
||||||
return table_print_with_pager(table, SD_JSON_FORMAT_OFF, arg_pager_flags, arg_legend);
|
return table_print_with_pager(table, SD_JSON_FORMAT_OFF, arg_pager_flags, arg_legend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct DescribeParams {
|
||||||
|
Version v;
|
||||||
|
sd_json_variant *contents_json;
|
||||||
|
bool newest;
|
||||||
|
bool available;
|
||||||
|
bool installed;
|
||||||
|
bool obsolete;
|
||||||
|
bool protected;
|
||||||
|
bool incomplete;
|
||||||
|
} DescribeParams;
|
||||||
|
|
||||||
|
static void describe_params_done(DescribeParams *p) {
|
||||||
|
assert(p);
|
||||||
|
|
||||||
|
version_done(&p->v);
|
||||||
|
sd_json_variant_unref(p->contents_json);
|
||||||
|
}
|
||||||
|
|
||||||
static int parse_describe(sd_bus_message *reply, Version *ret) {
|
static int parse_describe(sd_bus_message *reply, Version *ret) {
|
||||||
Version v = {};
|
|
||||||
char *version_json = NULL;
|
char *version_json = NULL;
|
||||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *json = NULL, *contents_json = NULL;
|
_cleanup_(sd_json_variant_unrefp) sd_json_variant *json = NULL;
|
||||||
bool newest = false, available = false, installed = false, obsolete = false, protected = false,
|
|
||||||
incomplete = false;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(reply);
|
assert(reply);
|
||||||
|
@ -342,36 +357,37 @@ static int parse_describe(sd_bus_message *reply, Version *ret) {
|
||||||
|
|
||||||
assert(sd_json_variant_is_object(json));
|
assert(sd_json_variant_is_object(json));
|
||||||
|
|
||||||
r = sd_json_dispatch(json,
|
static const sd_json_dispatch_field dispatch_table[] = {
|
||||||
(const sd_json_dispatch_field[]) {
|
{ "version", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(DescribeParams, v.version), 0 },
|
||||||
{ "version", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, PTR_TO_SIZE(&v.version), 0 },
|
{ "newest", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(DescribeParams, newest), 0 },
|
||||||
{ "newest", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, PTR_TO_SIZE(&newest), 0 },
|
{ "available", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(DescribeParams, available), 0 },
|
||||||
{ "available", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, PTR_TO_SIZE(&available), 0 },
|
{ "installed", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(DescribeParams, installed), 0 },
|
||||||
{ "installed", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, PTR_TO_SIZE(&installed), 0 },
|
{ "obsolete", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(DescribeParams, obsolete), 0 },
|
||||||
{ "obsolete", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, PTR_TO_SIZE(&obsolete), 0 },
|
{ "protected", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(DescribeParams, protected), 0 },
|
||||||
{ "protected", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, PTR_TO_SIZE(&protected), 0 },
|
{ "incomplete", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(DescribeParams, incomplete), 0 },
|
||||||
{ "incomplete", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, PTR_TO_SIZE(&incomplete), 0 },
|
{ "changelog_urls", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_strv, offsetof(DescribeParams, v.changelog), 0 },
|
||||||
{ "changelog_urls", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_strv, PTR_TO_SIZE(&v.changelog), 0 },
|
{ "contents", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_variant, offsetof(DescribeParams, contents_json), 0 },
|
||||||
{ "contents", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_variant, PTR_TO_SIZE(&contents_json), 0 },
|
|
||||||
{},
|
{},
|
||||||
},
|
};
|
||||||
SD_JSON_ALLOW_EXTENSIONS,
|
|
||||||
/* userdata= */ NULL);
|
_cleanup_(describe_params_done) DescribeParams p = {};
|
||||||
|
|
||||||
|
r = sd_json_dispatch(json, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, &p);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to parse JSON: %m");
|
return log_error_errno(r, "Failed to parse JSON: %m");
|
||||||
|
|
||||||
SET_FLAG(v.flags, UPDATE_NEWEST, newest);
|
SET_FLAG(p.v.flags, UPDATE_NEWEST, p.newest);
|
||||||
SET_FLAG(v.flags, UPDATE_AVAILABLE, available);
|
SET_FLAG(p.v.flags, UPDATE_AVAILABLE, p.available);
|
||||||
SET_FLAG(v.flags, UPDATE_INSTALLED, installed);
|
SET_FLAG(p.v.flags, UPDATE_INSTALLED, p.installed);
|
||||||
SET_FLAG(v.flags, UPDATE_OBSOLETE, obsolete);
|
SET_FLAG(p.v.flags, UPDATE_OBSOLETE, p.obsolete);
|
||||||
SET_FLAG(v.flags, UPDATE_PROTECTED, protected);
|
SET_FLAG(p.v.flags, UPDATE_PROTECTED, p.protected);
|
||||||
SET_FLAG(v.flags, UPDATE_INCOMPLETE, incomplete);
|
SET_FLAG(p.v.flags, UPDATE_INCOMPLETE, p.incomplete);
|
||||||
|
|
||||||
r = sd_json_variant_format(contents_json, 0, &v.contents_json);
|
r = sd_json_variant_format(p.contents_json, 0, &p.v.contents_json);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to format JSON for contents: %m");
|
return log_error_errno(r, "Failed to format JSON for contents: %m");
|
||||||
|
|
||||||
*ret = TAKE_STRUCT(v);
|
*ret = TAKE_STRUCT(p.v);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1141,6 +1141,18 @@ TEST(ASSERT) {
|
||||||
ASSERT_SIGNAL(ASSERT_OK_ERRNO(-1), SIGABRT);
|
ASSERT_SIGNAL(ASSERT_OK_ERRNO(-1), SIGABRT);
|
||||||
ASSERT_SIGNAL(ASSERT_OK_ERRNO(-ENOANO), SIGABRT);
|
ASSERT_SIGNAL(ASSERT_OK_ERRNO(-ENOANO), SIGABRT);
|
||||||
|
|
||||||
|
ASSERT_OK_ZERO_ERRNO(0);
|
||||||
|
ASSERT_SIGNAL(ASSERT_OK_ZERO_ERRNO(1), SIGABRT);
|
||||||
|
ASSERT_SIGNAL(ASSERT_OK_ZERO_ERRNO(255), SIGABRT);
|
||||||
|
ASSERT_SIGNAL(ASSERT_OK_ZERO_ERRNO(-1), SIGABRT);
|
||||||
|
ASSERT_SIGNAL(ASSERT_OK_ZERO_ERRNO(-ENOANO), SIGABRT);
|
||||||
|
|
||||||
|
ASSERT_OK_EQ_ERRNO(0, 0);
|
||||||
|
ASSERT_SIGNAL(ASSERT_OK_EQ_ERRNO(1, 0), SIGABRT);
|
||||||
|
ASSERT_SIGNAL(ASSERT_OK_EQ_ERRNO(255, 5), SIGABRT);
|
||||||
|
ASSERT_SIGNAL(ASSERT_OK_EQ_ERRNO(-1, 0), SIGABRT);
|
||||||
|
ASSERT_SIGNAL(ASSERT_OK_EQ_ERRNO(-ENOANO, 0), SIGABRT);
|
||||||
|
|
||||||
ASSERT_FAIL(-ENOENT);
|
ASSERT_FAIL(-ENOENT);
|
||||||
ASSERT_FAIL(-EPERM);
|
ASSERT_FAIL(-EPERM);
|
||||||
ASSERT_SIGNAL(ASSERT_FAIL(0), SIGABRT);
|
ASSERT_SIGNAL(ASSERT_FAIL(0), SIGABRT);
|
||||||
|
|
|
@ -54,46 +54,51 @@ static void test_pid_get_comm_one(pid_t pid) {
|
||||||
xsprintf(path, "/proc/"PID_FMT"/comm", pid);
|
xsprintf(path, "/proc/"PID_FMT"/comm", pid);
|
||||||
|
|
||||||
if (stat(path, &st) == 0) {
|
if (stat(path, &st) == 0) {
|
||||||
assert_se(pid_get_comm(pid, &a) >= 0);
|
ASSERT_OK(pid_get_comm(pid, &a));
|
||||||
log_info("PID"PID_FMT" comm: '%s'", pid, a);
|
log_info("PID"PID_FMT" comm: '%s'", pid, a);
|
||||||
} else
|
} else
|
||||||
log_warning("%s not exist.", path);
|
log_warning("%s not exist.", path);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(pid, 0, PROCESS_CMDLINE_COMM_FALLBACK, &c) >= 0);
|
ASSERT_OK(pid_get_cmdline(pid, 0, PROCESS_CMDLINE_COMM_FALLBACK, &c));
|
||||||
log_info("PID"PID_FMT" cmdline: '%s'", pid, c);
|
log_info("PID"PID_FMT" cmdline: '%s'", pid, c);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(pid, 8, 0, &d) >= 0);
|
ASSERT_OK(pid_get_cmdline(pid, 8, 0, &d));
|
||||||
log_info("PID"PID_FMT" cmdline truncated to 8: '%s'", pid, d);
|
log_info("PID"PID_FMT" cmdline truncated to 8: '%s'", pid, d);
|
||||||
|
|
||||||
free(d);
|
free(d);
|
||||||
assert_se(pid_get_cmdline(pid, 1, 0, &d) >= 0);
|
ASSERT_OK(pid_get_cmdline(pid, 1, 0, &d));
|
||||||
log_info("PID"PID_FMT" cmdline truncated to 1: '%s'", pid, d);
|
log_info("PID"PID_FMT" cmdline truncated to 1: '%s'", pid, d);
|
||||||
|
|
||||||
r = get_process_ppid(pid, &e);
|
r = get_process_ppid(pid, &e);
|
||||||
assert_se(pid == 1 ? r == -EADDRNOTAVAIL : r >= 0);
|
if (pid == 1)
|
||||||
|
ASSERT_ERROR(r, EADDRNOTAVAIL);
|
||||||
|
else
|
||||||
|
ASSERT_OK(r);
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
log_info("PID"PID_FMT" PPID: "PID_FMT, pid, e);
|
log_info("PID"PID_FMT" PPID: "PID_FMT, pid, e);
|
||||||
assert_se(e > 0);
|
ASSERT_GT(e, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_se(pid_is_kernel_thread(pid) == 0 || pid != 1);
|
ASSERT_TRUE(pid_is_kernel_thread(pid) == 0 || pid != 1);
|
||||||
|
|
||||||
r = get_process_exe(pid, &f);
|
r = get_process_exe(pid, &f);
|
||||||
assert_se(r >= 0 || r == -EACCES);
|
if (r != -EACCES)
|
||||||
|
ASSERT_OK(r);
|
||||||
log_info("PID"PID_FMT" exe: '%s'", pid, strna(f));
|
log_info("PID"PID_FMT" exe: '%s'", pid, strna(f));
|
||||||
|
|
||||||
assert_se(pid_get_uid(pid, &u) == 0);
|
ASSERT_OK_ZERO(pid_get_uid(pid, &u));
|
||||||
log_info("PID"PID_FMT" UID: "UID_FMT, pid, u);
|
log_info("PID"PID_FMT" UID: "UID_FMT, pid, u);
|
||||||
|
|
||||||
assert_se(get_process_gid(pid, &g) == 0);
|
ASSERT_OK_ZERO(get_process_gid(pid, &g));
|
||||||
log_info("PID"PID_FMT" GID: "GID_FMT, pid, g);
|
log_info("PID"PID_FMT" GID: "GID_FMT, pid, g);
|
||||||
|
|
||||||
r = get_process_environ(pid, &env);
|
r = get_process_environ(pid, &env);
|
||||||
assert_se(r >= 0 || r == -EACCES);
|
if (r != -EACCES)
|
||||||
|
ASSERT_OK(r);
|
||||||
log_info("PID"PID_FMT" strlen(environ): %zi", pid, env ? (ssize_t)strlen(env) : (ssize_t)-errno);
|
log_info("PID"PID_FMT" strlen(environ): %zi", pid, env ? (ssize_t)strlen(env) : (ssize_t)-errno);
|
||||||
|
|
||||||
if (!detect_container())
|
if (!detect_container() && pid == 1)
|
||||||
assert_se(get_ctty_devnr(pid, &h) == -ENXIO || pid != 1);
|
ASSERT_ERROR(get_ctty_devnr(pid, &h), ENXIO);
|
||||||
|
|
||||||
(void) getenv_for_pid(pid, "PATH", &i);
|
(void) getenv_for_pid(pid, "PATH", &i);
|
||||||
log_info("PID"PID_FMT" $PATH: '%s'", pid, strna(i));
|
log_info("PID"PID_FMT" $PATH: '%s'", pid, strna(i));
|
||||||
|
@ -136,14 +141,14 @@ static void test_pid_get_cmdline_one(pid_t pid) {
|
||||||
|
|
||||||
r = pid_get_cmdline_strv(pid, 0, &strv_a);
|
r = pid_get_cmdline_strv(pid, 0, &strv_a);
|
||||||
if (r >= 0)
|
if (r >= 0)
|
||||||
assert_se(joined = strv_join(strv_a, "\", \""));
|
ASSERT_NOT_NULL(joined = strv_join(strv_a, "\", \""));
|
||||||
log_info(" \"%s\"", r >= 0 ? joined : errno_to_name(r));
|
log_info(" \"%s\"", r >= 0 ? joined : errno_to_name(r));
|
||||||
|
|
||||||
joined = mfree(joined);
|
joined = mfree(joined);
|
||||||
|
|
||||||
r = pid_get_cmdline_strv(pid, PROCESS_CMDLINE_COMM_FALLBACK, &strv_b);
|
r = pid_get_cmdline_strv(pid, PROCESS_CMDLINE_COMM_FALLBACK, &strv_b);
|
||||||
if (r >= 0)
|
if (r >= 0)
|
||||||
assert_se(joined = strv_join(strv_b, "\", \""));
|
ASSERT_NOT_NULL(joined = strv_join(strv_b, "\", \""));
|
||||||
log_info(" \"%s\"", r >= 0 ? joined : errno_to_name(r));
|
log_info(" \"%s\"", r >= 0 ? joined : errno_to_name(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,13 +156,13 @@ TEST(pid_get_cmdline) {
|
||||||
_cleanup_closedir_ DIR *d = NULL;
|
_cleanup_closedir_ DIR *d = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert_se(proc_dir_open(&d) >= 0);
|
ASSERT_OK(proc_dir_open(&d));
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
r = proc_dir_read(d, &pid);
|
r = proc_dir_read(d, &pid);
|
||||||
assert_se(r >= 0);
|
ASSERT_OK(r);
|
||||||
|
|
||||||
if (r == 0) /* EOF */
|
if (r == 0) /* EOF */
|
||||||
break;
|
break;
|
||||||
|
@ -171,8 +176,8 @@ static void test_pid_get_comm_escape_one(const char *input, const char *output)
|
||||||
|
|
||||||
log_debug("input: <%s> — output: <%s>", input, output);
|
log_debug("input: <%s> — output: <%s>", input, output);
|
||||||
|
|
||||||
assert_se(prctl(PR_SET_NAME, input) >= 0);
|
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, input));
|
||||||
assert_se(pid_get_comm(0, &n) >= 0);
|
ASSERT_OK(pid_get_comm(0, &n));
|
||||||
|
|
||||||
log_debug("got: <%s>", n);
|
log_debug("got: <%s>", n);
|
||||||
|
|
||||||
|
@ -182,7 +187,7 @@ static void test_pid_get_comm_escape_one(const char *input, const char *output)
|
||||||
TEST(pid_get_comm_escape) {
|
TEST(pid_get_comm_escape) {
|
||||||
_cleanup_free_ char *saved = NULL;
|
_cleanup_free_ char *saved = NULL;
|
||||||
|
|
||||||
assert_se(pid_get_comm(0, &saved) >= 0);
|
ASSERT_OK(pid_get_comm(0, &saved));
|
||||||
|
|
||||||
test_pid_get_comm_escape_one("", "");
|
test_pid_get_comm_escape_one("", "");
|
||||||
test_pid_get_comm_escape_one("foo", "foo");
|
test_pid_get_comm_escape_one("foo", "foo");
|
||||||
|
@ -195,62 +200,62 @@ TEST(pid_get_comm_escape) {
|
||||||
test_pid_get_comm_escape_one("xxxxäöüß", "xxxx\\303\\244\\303\\266\\303\\274\\303\\237");
|
test_pid_get_comm_escape_one("xxxxäöüß", "xxxx\\303\\244\\303\\266\\303\\274\\303\\237");
|
||||||
test_pid_get_comm_escape_one("xxxxxäöüß", "xxxxx\\303\\244\\303\\266\\303\\274\\303\\237");
|
test_pid_get_comm_escape_one("xxxxxäöüß", "xxxxx\\303\\244\\303\\266\\303\\274\\303\\237");
|
||||||
|
|
||||||
assert_se(prctl(PR_SET_NAME, saved) >= 0);
|
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, saved));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pid_is_unwaited) {
|
TEST(pid_is_unwaited) {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
assert_se(pid >= 0);
|
ASSERT_OK_ERRNO(pid);
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
} else {
|
} else {
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
assert_se(waitpid(pid, &status, 0) == pid);
|
ASSERT_OK_EQ_ERRNO(waitpid(pid, &status, 0), pid);
|
||||||
assert_se(pid_is_unwaited(pid) == 0);
|
ASSERT_OK_ZERO(pid_is_unwaited(pid));
|
||||||
}
|
}
|
||||||
assert_se(pid_is_unwaited(getpid_cached()) > 0);
|
ASSERT_OK_POSITIVE(pid_is_unwaited(getpid_cached()));
|
||||||
assert_se(pid_is_unwaited(-1) < 0);
|
ASSERT_FAIL(pid_is_unwaited(-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pid_is_alive) {
|
TEST(pid_is_alive) {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
assert_se(pid >= 0);
|
ASSERT_OK_ERRNO(pid);
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
} else {
|
} else {
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
assert_se(waitpid(pid, &status, 0) == pid);
|
ASSERT_OK_EQ_ERRNO(waitpid(pid, &status, 0), pid);
|
||||||
assert_se(pid_is_alive(pid) == 0);
|
ASSERT_OK_ZERO(pid_is_alive(pid));
|
||||||
}
|
}
|
||||||
assert_se(pid_is_alive(getpid_cached()) > 0);
|
ASSERT_OK_POSITIVE(pid_is_alive(getpid_cached()));
|
||||||
assert_se(pid_is_alive(-1) < 0);
|
ASSERT_FAIL(pid_is_alive(-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(personality) {
|
TEST(personality) {
|
||||||
assert_se(personality_to_string(PER_LINUX));
|
ASSERT_NOT_NULL(personality_to_string(PER_LINUX));
|
||||||
assert_se(!personality_to_string(PERSONALITY_INVALID));
|
ASSERT_NULL(personality_to_string(PERSONALITY_INVALID));
|
||||||
|
|
||||||
ASSERT_STREQ(personality_to_string(PER_LINUX), architecture_to_string(native_architecture()));
|
ASSERT_STREQ(personality_to_string(PER_LINUX), architecture_to_string(native_architecture()));
|
||||||
|
|
||||||
assert_se(personality_from_string(personality_to_string(PER_LINUX)) == PER_LINUX);
|
ASSERT_EQ(personality_from_string(personality_to_string(PER_LINUX)), (unsigned long) PER_LINUX);
|
||||||
assert_se(personality_from_string(architecture_to_string(native_architecture())) == PER_LINUX);
|
ASSERT_EQ(personality_from_string(architecture_to_string(native_architecture())), (unsigned long) PER_LINUX);
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
ASSERT_STREQ(personality_to_string(PER_LINUX), "x86-64");
|
ASSERT_STREQ(personality_to_string(PER_LINUX), "x86-64");
|
||||||
ASSERT_STREQ(personality_to_string(PER_LINUX32), "x86");
|
ASSERT_STREQ(personality_to_string(PER_LINUX32), "x86");
|
||||||
|
|
||||||
assert_se(personality_from_string("x86-64") == PER_LINUX);
|
ASSERT_EQ(personality_from_string("x86-64"), (unsigned long) PER_LINUX);
|
||||||
assert_se(personality_from_string("x86") == PER_LINUX32);
|
ASSERT_EQ(personality_from_string("x86"), (unsigned long) PER_LINUX32);
|
||||||
assert_se(personality_from_string("ia64") == PERSONALITY_INVALID);
|
ASSERT_EQ(personality_from_string("ia64"), PERSONALITY_INVALID);
|
||||||
assert_se(personality_from_string(NULL) == PERSONALITY_INVALID);
|
ASSERT_EQ(personality_from_string(NULL), PERSONALITY_INVALID);
|
||||||
|
|
||||||
assert_se(personality_from_string(personality_to_string(PER_LINUX32)) == PER_LINUX32);
|
ASSERT_EQ(personality_from_string(personality_to_string(PER_LINUX32)), (unsigned long) PER_LINUX32);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,30 +293,31 @@ TEST(pid_get_cmdline_harder) {
|
||||||
|
|
||||||
(void) wait_for_terminate(pid, &si);
|
(void) wait_for_terminate(pid, &si);
|
||||||
|
|
||||||
assert_se(si.si_code == CLD_EXITED);
|
ASSERT_EQ(si.si_code, CLD_EXITED);
|
||||||
assert_se(si.si_status == 0);
|
ASSERT_OK_ZERO(si.si_status);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_se(pid == 0);
|
ASSERT_OK_ZERO(pid);
|
||||||
|
|
||||||
r = detach_mount_namespace();
|
r = detach_mount_namespace();
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_warning_errno(r, "detach mount namespace failed: %m");
|
log_warning_errno(r, "detach mount namespace failed: %m");
|
||||||
assert_se(ERRNO_IS_PRIVILEGE(r));
|
if (!ERRNO_IS_PRIVILEGE(r))
|
||||||
|
ASSERT_OK(r);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = mkostemp(path, O_CLOEXEC);
|
fd = mkostemp(path, O_CLOEXEC);
|
||||||
assert_se(fd >= 0);
|
ASSERT_OK_ERRNO(fd);
|
||||||
|
|
||||||
/* Note that we don't unmount the following bind-mount at the end of the test because the kernel
|
/* Note that we don't unmount the following bind-mount at the end of the test because the kernel
|
||||||
* will clear up its /proc/PID/ hierarchy automatically as soon as the test stops. */
|
* will clear up its /proc/PID/ hierarchy automatically as soon as the test stops. */
|
||||||
if (mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) < 0) {
|
if (mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) < 0) {
|
||||||
/* This happens under selinux… Abort the test in this case. */
|
/* This happens under selinux… Abort the test in this case. */
|
||||||
log_warning_errno(errno, "mount(..., \"/proc/self/cmdline\", \"bind\", ...) failed: %m");
|
log_warning_errno(errno, "mount(..., \"/proc/self/cmdline\", \"bind\", ...) failed: %m");
|
||||||
assert_se(IN_SET(errno, EPERM, EACCES));
|
ASSERT_TRUE(IN_SET(errno, EPERM, EACCES));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,197 +326,197 @@ TEST(pid_get_cmdline_harder) {
|
||||||
if (setrlimit(RLIMIT_STACK, &RLIMIT_MAKE_CONST(RLIM_INFINITY)) < 0)
|
if (setrlimit(RLIMIT_STACK, &RLIMIT_MAKE_CONST(RLIM_INFINITY)) < 0)
|
||||||
log_warning("Testing without RLIMIT_STACK=infinity");
|
log_warning("Testing without RLIMIT_STACK=infinity");
|
||||||
|
|
||||||
assert_se(unlink(path) >= 0);
|
ASSERT_OK_ERRNO(unlink(path));
|
||||||
|
|
||||||
assert_se(prctl(PR_SET_NAME, "testa") >= 0);
|
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "testa"));
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, SIZE_MAX, 0, &line) == -ENOENT);
|
ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "[testa]");
|
ASSERT_STREQ(line, "[testa]");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_QUOTE, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_QUOTE, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "\"[testa]\""); /* quoting is enabled here */
|
ASSERT_STREQ(line, "\"[testa]\""); /* quoting is enabled here */
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 0, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 0, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "");
|
ASSERT_STREQ(line, "");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
ASSERT_STREQ(line, "…");
|
ASSERT_STREQ(line, "…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
ASSERT_STREQ(line, "[…");
|
ASSERT_STREQ(line, "[…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
ASSERT_STREQ(line, "[t…");
|
ASSERT_STREQ(line, "[t…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
ASSERT_STREQ(line, "[te…");
|
ASSERT_STREQ(line, "[te…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
ASSERT_STREQ(line, "[tes…");
|
ASSERT_STREQ(line, "[tes…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
ASSERT_STREQ(line, "[test…");
|
ASSERT_STREQ(line, "[test…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
ASSERT_STREQ(line, "[testa]");
|
ASSERT_STREQ(line, "[testa]");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
ASSERT_STREQ(line, "[testa]");
|
ASSERT_STREQ(line, "[testa]");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args) >= 0);
|
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
|
||||||
assert_se(strv_equal(args, STRV_MAKE("[testa]")));
|
ASSERT_TRUE(strv_equal(args, STRV_MAKE("[testa]")));
|
||||||
args = strv_free(args);
|
args = strv_free(args);
|
||||||
|
|
||||||
/* Test with multiple arguments that don't require quoting */
|
/* Test with multiple arguments that don't require quoting */
|
||||||
|
|
||||||
assert_se(write(fd, "foo\0bar", 8) == 8);
|
ASSERT_OK_EQ_ERRNO(write(fd, "foo\0bar", 8), 8);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, SIZE_MAX, 0, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, 0, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar");
|
ASSERT_STREQ(line, "foo bar");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
ASSERT_STREQ(line, "foo bar");
|
ASSERT_STREQ(line, "foo bar");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args) >= 0);
|
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
|
||||||
assert_se(strv_equal(args, STRV_MAKE("foo", "bar")));
|
ASSERT_TRUE(strv_equal(args, STRV_MAKE("foo", "bar")));
|
||||||
args = strv_free(args);
|
args = strv_free(args);
|
||||||
|
|
||||||
assert_se(write(fd, "quux", 4) == 4);
|
ASSERT_OK_EQ_ERRNO(write(fd, "quux", 4), 4);
|
||||||
assert_se(pid_get_cmdline(0, SIZE_MAX, 0, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, 0, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar quux");
|
ASSERT_STREQ(line, "foo bar quux");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar quux");
|
ASSERT_STREQ(line, "foo bar quux");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "…");
|
ASSERT_STREQ(line, "…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "f…");
|
ASSERT_STREQ(line, "f…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "fo…");
|
ASSERT_STREQ(line, "fo…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo…");
|
ASSERT_STREQ(line, "foo…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo …");
|
ASSERT_STREQ(line, "foo …");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo b…");
|
ASSERT_STREQ(line, "foo b…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo ba…");
|
ASSERT_STREQ(line, "foo ba…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar…");
|
ASSERT_STREQ(line, "foo bar…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 9, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 9, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar …");
|
ASSERT_STREQ(line, "foo bar …");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar q…");
|
ASSERT_STREQ(line, "foo bar q…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar qu…");
|
ASSERT_STREQ(line, "foo bar qu…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar quux");
|
ASSERT_STREQ(line, "foo bar quux");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 13, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 13, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar quux");
|
ASSERT_STREQ(line, "foo bar quux");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 14, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 14, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar quux");
|
ASSERT_STREQ(line, "foo bar quux");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 1000, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 1000, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar quux");
|
ASSERT_STREQ(line, "foo bar quux");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args) >= 0);
|
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
|
||||||
assert_se(strv_equal(args, STRV_MAKE("foo", "bar", "quux")));
|
ASSERT_TRUE(strv_equal(args, STRV_MAKE("foo", "bar", "quux")));
|
||||||
args = strv_free(args);
|
args = strv_free(args);
|
||||||
|
|
||||||
assert_se(ftruncate(fd, 0) >= 0);
|
ASSERT_OK_ERRNO(ftruncate(fd, 0));
|
||||||
assert_se(prctl(PR_SET_NAME, "aaaa bbbb cccc") >= 0);
|
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "aaaa bbbb cccc"));
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, SIZE_MAX, 0, &line) == -ENOENT);
|
ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "[aaaa bbbb cccc]");
|
ASSERT_STREQ(line, "[aaaa bbbb cccc]");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "[aaaa bbb…");
|
ASSERT_STREQ(line, "[aaaa bbb…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "[aaaa bbbb…");
|
ASSERT_STREQ(line, "[aaaa bbbb…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "[aaaa bbbb …");
|
ASSERT_STREQ(line, "[aaaa bbbb …");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args) >= 0);
|
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
|
||||||
assert_se(strv_equal(args, STRV_MAKE("[aaaa bbbb cccc]")));
|
ASSERT_TRUE(strv_equal(args, STRV_MAKE("[aaaa bbbb cccc]")));
|
||||||
args = strv_free(args);
|
args = strv_free(args);
|
||||||
|
|
||||||
/* Test with multiple arguments that do require quoting */
|
/* Test with multiple arguments that do require quoting */
|
||||||
|
@ -520,24 +526,24 @@ TEST(pid_get_cmdline_harder) {
|
||||||
#define EXPECT1p "foo $'\\'bar\\'' $'\"bar$\"' $'x y z' $'!``'"
|
#define EXPECT1p "foo $'\\'bar\\'' $'\"bar$\"' $'x y z' $'!``'"
|
||||||
#define EXPECT1v STRV_MAKE("foo", "'bar'", "\"bar$\"", "x y z", "!``")
|
#define EXPECT1v STRV_MAKE("foo", "'bar'", "\"bar$\"", "x y z", "!``")
|
||||||
|
|
||||||
assert_se(lseek(fd, SEEK_SET, 0) == 0);
|
ASSERT_OK_ZERO_ERRNO(lseek(fd, SEEK_SET, 0));
|
||||||
assert_se(write(fd, CMDLINE1, sizeof CMDLINE1) == sizeof CMDLINE1);
|
ASSERT_OK_EQ_ERRNO(write(fd, CMDLINE1, sizeof(CMDLINE1)), (ssize_t) sizeof(CMDLINE1));
|
||||||
assert_se(ftruncate(fd, sizeof CMDLINE1) == 0);
|
ASSERT_OK_ZERO_ERRNO(ftruncate(fd, sizeof(CMDLINE1)));
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line));
|
||||||
log_debug("got: ==%s==", line);
|
log_debug("got: ==%s==", line);
|
||||||
log_debug("exp: ==%s==", EXPECT1);
|
log_debug("exp: ==%s==", EXPECT1);
|
||||||
ASSERT_STREQ(line, EXPECT1);
|
ASSERT_STREQ(line, EXPECT1);
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line));
|
||||||
log_debug("got: ==%s==", line);
|
log_debug("got: ==%s==", line);
|
||||||
log_debug("exp: ==%s==", EXPECT1p);
|
log_debug("exp: ==%s==", EXPECT1p);
|
||||||
ASSERT_STREQ(line, EXPECT1p);
|
ASSERT_STREQ(line, EXPECT1p);
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline_strv(0, 0, &args) >= 0);
|
ASSERT_OK(pid_get_cmdline_strv(0, 0, &args));
|
||||||
assert_se(strv_equal(args, EXPECT1v));
|
ASSERT_TRUE(strv_equal(args, EXPECT1v));
|
||||||
args = strv_free(args);
|
args = strv_free(args);
|
||||||
|
|
||||||
#define CMDLINE2 "foo\0\1\2\3\0\0"
|
#define CMDLINE2 "foo\0\1\2\3\0\0"
|
||||||
|
@ -545,24 +551,24 @@ TEST(pid_get_cmdline_harder) {
|
||||||
#define EXPECT2p "foo $'\\001\\002\\003'"
|
#define EXPECT2p "foo $'\\001\\002\\003'"
|
||||||
#define EXPECT2v STRV_MAKE("foo", "\1\2\3")
|
#define EXPECT2v STRV_MAKE("foo", "\1\2\3")
|
||||||
|
|
||||||
assert_se(lseek(fd, SEEK_SET, 0) == 0);
|
ASSERT_OK_ZERO_ERRNO(lseek(fd, SEEK_SET, 0));
|
||||||
assert_se(write(fd, CMDLINE2, sizeof CMDLINE2) == sizeof CMDLINE2);
|
ASSERT_OK_EQ_ERRNO(write(fd, CMDLINE2, sizeof(CMDLINE2)), (ssize_t) sizeof(CMDLINE2));
|
||||||
assert_se(ftruncate(fd, sizeof CMDLINE2) == 0);
|
ASSERT_OK_ZERO_ERRNO(ftruncate(fd, sizeof CMDLINE2));
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line));
|
||||||
log_debug("got: ==%s==", line);
|
log_debug("got: ==%s==", line);
|
||||||
log_debug("exp: ==%s==", EXPECT2);
|
log_debug("exp: ==%s==", EXPECT2);
|
||||||
ASSERT_STREQ(line, EXPECT2);
|
ASSERT_STREQ(line, EXPECT2);
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line) >= 0);
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line));
|
||||||
log_debug("got: ==%s==", line);
|
log_debug("got: ==%s==", line);
|
||||||
log_debug("exp: ==%s==", EXPECT2p);
|
log_debug("exp: ==%s==", EXPECT2p);
|
||||||
ASSERT_STREQ(line, EXPECT2p);
|
ASSERT_STREQ(line, EXPECT2p);
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline_strv(0, 0, &args) >= 0);
|
ASSERT_OK(pid_get_cmdline_strv(0, 0, &args));
|
||||||
assert_se(strv_equal(args, EXPECT2v));
|
ASSERT_TRUE(strv_equal(args, EXPECT2v));
|
||||||
args = strv_free(args);
|
args = strv_free(args);
|
||||||
|
|
||||||
safe_close(fd);
|
safe_close(fd);
|
||||||
|
@ -577,10 +583,11 @@ TEST(getpid_cached) {
|
||||||
b = getpid_cached();
|
b = getpid_cached();
|
||||||
c = getpid();
|
c = getpid();
|
||||||
|
|
||||||
assert_se(a == b && a == c);
|
ASSERT_EQ(a, b);
|
||||||
|
ASSERT_EQ(a, c);
|
||||||
|
|
||||||
child = fork();
|
child = fork();
|
||||||
assert_se(child >= 0);
|
ASSERT_OK_ERRNO(child);
|
||||||
|
|
||||||
if (child == 0) {
|
if (child == 0) {
|
||||||
/* In child */
|
/* In child */
|
||||||
|
@ -588,7 +595,8 @@ TEST(getpid_cached) {
|
||||||
b = getpid_cached();
|
b = getpid_cached();
|
||||||
c = getpid();
|
c = getpid();
|
||||||
|
|
||||||
assert_se(a == b && a == c);
|
ASSERT_EQ(a, b);
|
||||||
|
ASSERT_EQ(a, c);
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,11 +604,13 @@ TEST(getpid_cached) {
|
||||||
e = getpid_cached();
|
e = getpid_cached();
|
||||||
f = getpid();
|
f = getpid();
|
||||||
|
|
||||||
assert_se(a == d && a == e && a == f);
|
ASSERT_EQ(a, d);
|
||||||
|
ASSERT_EQ(a, e);
|
||||||
|
ASSERT_EQ(a, f);
|
||||||
|
|
||||||
assert_se(wait_for_terminate(child, &si) >= 0);
|
ASSERT_OK(wait_for_terminate(child, &si));
|
||||||
assert_se(si.si_status == 0);
|
ASSERT_EQ(si.si_status, 0);
|
||||||
assert_se(si.si_code == CLD_EXITED);
|
ASSERT_EQ(si.si_code, CLD_EXITED);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(getpid_measure) {
|
TEST(getpid_measure) {
|
||||||
|
@ -635,7 +645,7 @@ TEST(safe_fork) {
|
||||||
BLOCK_SIGNALS(SIGCHLD);
|
BLOCK_SIGNALS(SIGCHLD);
|
||||||
|
|
||||||
r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_REOPEN_LOG, &pid);
|
r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_REOPEN_LOG, &pid);
|
||||||
assert_se(r >= 0);
|
ASSERT_OK(r);
|
||||||
|
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
/* child */
|
/* child */
|
||||||
|
@ -644,43 +654,42 @@ TEST(safe_fork) {
|
||||||
_exit(88);
|
_exit(88);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_se(wait_for_terminate(pid, &status) >= 0);
|
ASSERT_OK(wait_for_terminate(pid, &status));
|
||||||
assert_se(status.si_code == CLD_EXITED);
|
ASSERT_EQ(status.si_code, CLD_EXITED);
|
||||||
assert_se(status.si_status == 88);
|
ASSERT_EQ(status.si_status, 88);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pid_to_ptr) {
|
TEST(pid_to_ptr) {
|
||||||
assert_se(PTR_TO_PID(NULL) == 0);
|
ASSERT_EQ(PTR_TO_PID(NULL), 0);
|
||||||
ASSERT_NULL(PID_TO_PTR(0));
|
ASSERT_NULL(PID_TO_PTR(0));
|
||||||
|
|
||||||
assert_se(PTR_TO_PID(PID_TO_PTR(1)) == 1);
|
ASSERT_EQ(PTR_TO_PID(PID_TO_PTR(1)), 1);
|
||||||
assert_se(PTR_TO_PID(PID_TO_PTR(2)) == 2);
|
ASSERT_EQ(PTR_TO_PID(PID_TO_PTR(2)), 2);
|
||||||
assert_se(PTR_TO_PID(PID_TO_PTR(-1)) == -1);
|
ASSERT_EQ(PTR_TO_PID(PID_TO_PTR(-1)), -1);
|
||||||
assert_se(PTR_TO_PID(PID_TO_PTR(-2)) == -2);
|
ASSERT_EQ(PTR_TO_PID(PID_TO_PTR(-2)), -2);
|
||||||
|
|
||||||
assert_se(PTR_TO_PID(PID_TO_PTR(INT16_MAX)) == INT16_MAX);
|
ASSERT_EQ(PTR_TO_PID(PID_TO_PTR(INT16_MAX)), INT16_MAX);
|
||||||
assert_se(PTR_TO_PID(PID_TO_PTR(INT16_MIN)) == INT16_MIN);
|
ASSERT_EQ(PTR_TO_PID(PID_TO_PTR(INT16_MIN)), INT16_MIN);
|
||||||
|
|
||||||
assert_se(PTR_TO_PID(PID_TO_PTR(INT32_MAX)) == INT32_MAX);
|
ASSERT_EQ(PTR_TO_PID(PID_TO_PTR(INT32_MAX)), INT32_MAX);
|
||||||
assert_se(PTR_TO_PID(PID_TO_PTR(INT32_MIN)) == INT32_MIN);
|
ASSERT_EQ(PTR_TO_PID(PID_TO_PTR(INT32_MIN)), INT32_MIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_ioprio_class_from_to_string_one(const char *val, int expected, int normalized) {
|
static void test_ioprio_class_from_to_string_one(const char *val, int expected, int normalized) {
|
||||||
assert_se(ioprio_class_from_string(val) == expected);
|
ASSERT_EQ(ioprio_class_from_string(val), expected);
|
||||||
if (expected >= 0) {
|
if (expected >= 0) {
|
||||||
_cleanup_free_ char *s = NULL;
|
_cleanup_free_ char *s = NULL;
|
||||||
unsigned ret;
|
unsigned ret;
|
||||||
int combined;
|
int combined;
|
||||||
|
|
||||||
assert_se(ioprio_class_to_string_alloc(expected, &s) == 0);
|
ASSERT_OK_ZERO(ioprio_class_to_string_alloc(expected, &s));
|
||||||
/* We sometimes get a class number and sometimes a name back */
|
/* We sometimes get a class number and sometimes a name back */
|
||||||
assert_se(streq(s, val) ||
|
ASSERT_TRUE(streq(s, val) || safe_atou(val, &ret) == 0);
|
||||||
safe_atou(val, &ret) == 0);
|
|
||||||
|
|
||||||
/* Make sure normalization works, i.e. NONE → BE gets normalized */
|
/* Make sure normalization works, i.e. NONE → BE gets normalized */
|
||||||
combined = ioprio_normalize(ioprio_prio_value(expected, 0));
|
combined = ioprio_normalize(ioprio_prio_value(expected, 0));
|
||||||
assert_se(ioprio_prio_class(combined) == normalized);
|
ASSERT_EQ(ioprio_prio_class(combined), normalized);
|
||||||
assert_se(expected != IOPRIO_CLASS_NONE || ioprio_prio_data(combined) == 4);
|
ASSERT_TRUE(expected != IOPRIO_CLASS_NONE || ioprio_prio_data(combined) == 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -701,8 +710,8 @@ TEST(setpriority_closest) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = safe_fork("(test-setprio)",
|
r = safe_fork("(test-setprio)",
|
||||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG, NULL);
|
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG|FORK_REOPEN_LOG, NULL);
|
||||||
assert_se(r >= 0);
|
ASSERT_OK(r);
|
||||||
|
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
bool full_test;
|
bool full_test;
|
||||||
|
@ -713,16 +722,21 @@ TEST(setpriority_closest) {
|
||||||
if (setrlimit(RLIMIT_NICE, &RLIMIT_MAKE_CONST(30)) < 0) {
|
if (setrlimit(RLIMIT_NICE, &RLIMIT_MAKE_CONST(30)) < 0) {
|
||||||
/* If this fails we are probably unprivileged or in a userns of some kind, let's skip
|
/* If this fails we are probably unprivileged or in a userns of some kind, let's skip
|
||||||
* the full test */
|
* the full test */
|
||||||
assert_se(ERRNO_IS_PRIVILEGE(errno));
|
if (!ERRNO_IS_PRIVILEGE(errno))
|
||||||
|
ASSERT_OK_ERRNO(-1);
|
||||||
full_test = false;
|
full_test = false;
|
||||||
} else {
|
} else {
|
||||||
/* However, if the hard limit was above 30, setrlimit would succeed unprivileged, so
|
/* However, if the hard limit was above 30, setrlimit would succeed unprivileged, so
|
||||||
* check if the UID/GID can be changed before enabling the full test. */
|
* check if the UID/GID can be changed before enabling the full test. */
|
||||||
if (setresgid(GID_NOBODY, GID_NOBODY, GID_NOBODY) < 0) {
|
if (setresgid(GID_NOBODY, GID_NOBODY, GID_NOBODY) < 0) {
|
||||||
assert_se(ERRNO_IS_PRIVILEGE(errno));
|
/* If the nobody user does not exist (user namespace) we get EINVAL. */
|
||||||
|
if (!ERRNO_IS_PRIVILEGE(errno) && errno != EINVAL)
|
||||||
|
ASSERT_OK_ERRNO(-1);
|
||||||
full_test = false;
|
full_test = false;
|
||||||
} else if (setresuid(UID_NOBODY, UID_NOBODY, UID_NOBODY) < 0) {
|
} else if (setresuid(UID_NOBODY, UID_NOBODY, UID_NOBODY) < 0) {
|
||||||
assert_se(ERRNO_IS_PRIVILEGE(errno));
|
/* If the nobody user does not exist (user namespace) we get EINVAL. */
|
||||||
|
if (!ERRNO_IS_PRIVILEGE(errno) && errno != EINVAL)
|
||||||
|
ASSERT_OK_ERRNO(-1);
|
||||||
full_test = false;
|
full_test = false;
|
||||||
} else
|
} else
|
||||||
full_test = true;
|
full_test = true;
|
||||||
|
@ -730,61 +744,69 @@ TEST(setpriority_closest) {
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
p = getpriority(PRIO_PROCESS, 0);
|
p = getpriority(PRIO_PROCESS, 0);
|
||||||
assert_se(errno == 0);
|
ASSERT_EQ(errno, 0);
|
||||||
|
|
||||||
/* It should always be possible to set our nice level to the current one */
|
/* It should always be possible to set our nice level to the current one */
|
||||||
assert_se(setpriority_closest(p) > 0);
|
ASSERT_OK_POSITIVE(setpriority_closest(p));
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
q = getpriority(PRIO_PROCESS, 0);
|
q = getpriority(PRIO_PROCESS, 0);
|
||||||
assert_se(errno == 0 && p == q);
|
ASSERT_EQ(errno, 0);
|
||||||
|
ASSERT_EQ(p, q);
|
||||||
|
|
||||||
/* It should also be possible to set the nice level to one higher */
|
/* It should also be possible to set the nice level to one higher */
|
||||||
if (p < PRIO_MAX-1) {
|
if (p < PRIO_MAX-1) {
|
||||||
assert_se(setpriority_closest(++p) > 0);
|
ASSERT_OK_POSITIVE(setpriority_closest(++p));
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
q = getpriority(PRIO_PROCESS, 0);
|
q = getpriority(PRIO_PROCESS, 0);
|
||||||
assert_se(errno == 0 && p == q);
|
ASSERT_EQ(errno, 0);
|
||||||
|
ASSERT_EQ(p, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* It should also be possible to set the nice level to two higher */
|
/* It should also be possible to set the nice level to two higher */
|
||||||
if (p < PRIO_MAX-1) {
|
if (p < PRIO_MAX-1) {
|
||||||
assert_se(setpriority_closest(++p) > 0);
|
ASSERT_OK_POSITIVE(setpriority_closest(++p));
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
q = getpriority(PRIO_PROCESS, 0);
|
q = getpriority(PRIO_PROCESS, 0);
|
||||||
assert_se(errno == 0 && p == q);
|
ASSERT_EQ(errno, 0);
|
||||||
|
ASSERT_EQ(p, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (full_test) {
|
if (full_test) {
|
||||||
/* These two should work, given the RLIMIT_NICE we set above */
|
/* These two should work, given the RLIMIT_NICE we set above */
|
||||||
assert_se(setpriority_closest(-10) > 0);
|
ASSERT_OK_POSITIVE(setpriority_closest(-10));
|
||||||
errno = 0;
|
errno = 0;
|
||||||
q = getpriority(PRIO_PROCESS, 0);
|
q = getpriority(PRIO_PROCESS, 0);
|
||||||
assert_se(errno == 0 && q == -10);
|
ASSERT_EQ(errno, 0);
|
||||||
|
ASSERT_EQ(q, -10);
|
||||||
|
|
||||||
assert_se(setpriority_closest(-9) > 0);
|
ASSERT_OK_POSITIVE(setpriority_closest(-9));
|
||||||
errno = 0;
|
errno = 0;
|
||||||
q = getpriority(PRIO_PROCESS, 0);
|
q = getpriority(PRIO_PROCESS, 0);
|
||||||
assert_se(errno == 0 && q == -9);
|
ASSERT_EQ(errno, 0);
|
||||||
|
ASSERT_EQ(q, -9);
|
||||||
|
|
||||||
/* This should succeed but should be clamped to the limit */
|
/* This should succeed but should be clamped to the limit */
|
||||||
assert_se(setpriority_closest(-11) == 0);
|
ASSERT_OK_ZERO(setpriority_closest(-11));
|
||||||
errno = 0;
|
errno = 0;
|
||||||
q = getpriority(PRIO_PROCESS, 0);
|
q = getpriority(PRIO_PROCESS, 0);
|
||||||
assert_se(errno == 0 && q == -10);
|
ASSERT_EQ(errno, 0);
|
||||||
|
ASSERT_EQ(q, -10);
|
||||||
|
|
||||||
assert_se(setpriority_closest(-8) > 0);
|
ASSERT_OK_POSITIVE(setpriority_closest(-8));
|
||||||
errno = 0;
|
errno = 0;
|
||||||
q = getpriority(PRIO_PROCESS, 0);
|
q = getpriority(PRIO_PROCESS, 0);
|
||||||
assert_se(errno == 0 && q == -8);
|
ASSERT_EQ(errno, 0);
|
||||||
|
ASSERT_EQ(q, -8);
|
||||||
|
|
||||||
/* This should succeed but should be clamped to the limit */
|
/* This should succeed but should be clamped to the limit */
|
||||||
assert_se(setpriority_closest(-12) == 0);
|
ASSERT_OK_ZERO(setpriority_closest(-12));
|
||||||
errno = 0;
|
errno = 0;
|
||||||
q = getpriority(PRIO_PROCESS, 0);
|
q = getpriority(PRIO_PROCESS, 0);
|
||||||
assert_se(errno == 0 && q == -10);
|
ASSERT_EQ(errno, 0);
|
||||||
|
ASSERT_EQ(q, -10);
|
||||||
}
|
}
|
||||||
|
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
|
@ -795,10 +817,10 @@ TEST(get_process_ppid) {
|
||||||
uint64_t limit;
|
uint64_t limit;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert_se(get_process_ppid(1, NULL) == -EADDRNOTAVAIL);
|
ASSERT_ERROR(get_process_ppid(1, NULL), EADDRNOTAVAIL);
|
||||||
|
|
||||||
/* the process with the PID above the global limit definitely doesn't exist. Verify that */
|
/* the process with the PID above the global limit definitely doesn't exist. Verify that */
|
||||||
assert_se(procfs_get_pid_max(&limit) >= 0);
|
ASSERT_OK(procfs_get_pid_max(&limit));
|
||||||
log_debug("kernel.pid_max = %"PRIu64, limit);
|
log_debug("kernel.pid_max = %"PRIu64, limit);
|
||||||
|
|
||||||
if (limit < INT_MAX) {
|
if (limit < INT_MAX) {
|
||||||
|
@ -817,10 +839,10 @@ TEST(get_process_ppid) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_se(r >= 0);
|
ASSERT_OK(r);
|
||||||
|
|
||||||
assert_se(pid_get_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &c1) >= 0);
|
ASSERT_OK(pid_get_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &c1));
|
||||||
assert_se(pid_get_cmdline(ppid, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &c2) >= 0);
|
ASSERT_OK(pid_get_cmdline(ppid, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &c2));
|
||||||
|
|
||||||
log_info("Parent of " PID_FMT " (%s) is " PID_FMT " (%s).", pid, c1, ppid, c2);
|
log_info("Parent of " PID_FMT " (%s) is " PID_FMT " (%s).", pid, c1, ppid, c2);
|
||||||
|
|
||||||
|
@ -831,19 +853,20 @@ TEST(get_process_ppid) {
|
||||||
TEST(set_oom_score_adjust) {
|
TEST(set_oom_score_adjust) {
|
||||||
int a, b, r;
|
int a, b, r;
|
||||||
|
|
||||||
assert_se(get_oom_score_adjust(&a) >= 0);
|
ASSERT_OK(get_oom_score_adjust(&a));
|
||||||
|
|
||||||
r = set_oom_score_adjust(OOM_SCORE_ADJ_MIN);
|
r = set_oom_score_adjust(OOM_SCORE_ADJ_MIN);
|
||||||
assert_se(r >= 0 || ERRNO_IS_PRIVILEGE(r));
|
if (!ERRNO_IS_PRIVILEGE(r))
|
||||||
|
ASSERT_OK(r);
|
||||||
|
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
assert_se(get_oom_score_adjust(&b) >= 0);
|
ASSERT_OK(get_oom_score_adjust(&b));
|
||||||
assert_se(b == OOM_SCORE_ADJ_MIN);
|
ASSERT_EQ(b, OOM_SCORE_ADJ_MIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_se(set_oom_score_adjust(a) >= 0);
|
ASSERT_OK(set_oom_score_adjust(a));
|
||||||
assert_se(get_oom_score_adjust(&b) >= 0);
|
ASSERT_OK(get_oom_score_adjust(&b));
|
||||||
assert_se(b == a);
|
ASSERT_EQ(b, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* dummy_thread(void *p) {
|
static void* dummy_thread(void *p) {
|
||||||
|
@ -851,10 +874,10 @@ static void* dummy_thread(void *p) {
|
||||||
char x;
|
char x;
|
||||||
|
|
||||||
/* let main thread know we are ready */
|
/* let main thread know we are ready */
|
||||||
assert_se(write(fd, &(const char) { 'x' }, 1) == 1);
|
ASSERT_OK_EQ_ERRNO(write(fd, &(const char) { 'x' }, 1), 1);
|
||||||
|
|
||||||
/* wait for the main thread to tell us to shut down */
|
/* wait for the main thread to tell us to shut down */
|
||||||
assert_se(read(fd, &x, 1) == 1);
|
ASSERT_OK_EQ_ERRNO(read(fd, &x, 1), 1);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -862,38 +885,42 @@ TEST(get_process_threads) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* Run this test in a child, so that we can guarantee there's exactly one thread around in the child */
|
/* Run this test in a child, so that we can guarantee there's exactly one thread around in the child */
|
||||||
r = safe_fork("(nthreads)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_WAIT|FORK_LOG, NULL);
|
r = safe_fork("(nthreads)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG, NULL);
|
||||||
assert_se(r >= 0);
|
ASSERT_OK(r);
|
||||||
|
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
_cleanup_close_pair_ int pfd[2] = EBADF_PAIR, ppfd[2] = EBADF_PAIR;
|
_cleanup_close_pair_ int pfd[2] = EBADF_PAIR, ppfd[2] = EBADF_PAIR;
|
||||||
pthread_t t, tt;
|
pthread_t t, tt;
|
||||||
char x;
|
char x;
|
||||||
|
|
||||||
assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, pfd) >= 0);
|
ASSERT_OK_ERRNO(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, pfd));
|
||||||
assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, ppfd) >= 0);
|
ASSERT_OK_ERRNO(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, ppfd));
|
||||||
|
|
||||||
assert_se(get_process_threads(0) == 1);
|
ASSERT_OK_EQ(get_process_threads(0), 1);
|
||||||
assert_se(pthread_create(&t, NULL, &dummy_thread, FD_TO_PTR(pfd[0])) == 0);
|
ASSERT_OK_ZERO_ERRNO(pthread_create(&t, NULL, &dummy_thread, FD_TO_PTR(pfd[0])));
|
||||||
assert_se(read(pfd[1], &x, 1) == 1);
|
ASSERT_OK_EQ_ERRNO(read(pfd[1], &x, 1), 1);
|
||||||
assert_se(get_process_threads(0) == 2);
|
ASSERT_OK_EQ(get_process_threads(0), 2);
|
||||||
assert_se(pthread_create(&tt, NULL, &dummy_thread, FD_TO_PTR(ppfd[0])) == 0);
|
ASSERT_OK_ZERO_ERRNO(pthread_create(&tt, NULL, &dummy_thread, FD_TO_PTR(ppfd[0])));
|
||||||
assert_se(read(ppfd[1], &x, 1) == 1);
|
ASSERT_OK_EQ_ERRNO(read(ppfd[1], &x, 1), 1);
|
||||||
assert_se(get_process_threads(0) == 3);
|
ASSERT_OK_EQ(get_process_threads(0), 3);
|
||||||
|
|
||||||
assert_se(write(pfd[1], &(const char) { 'x' }, 1) == 1);
|
ASSERT_OK_EQ_ERRNO(write(pfd[1], &(const char) { 'x' }, 1), 1);
|
||||||
assert_se(pthread_join(t, NULL) == 0);
|
ASSERT_OK_ZERO_ERRNO(pthread_join(t, NULL));
|
||||||
|
|
||||||
/* the value reported via /proc/ is decreased asynchronously, and there appears to be no nice
|
/* the value reported via /proc/ is decreased asynchronously, and there appears to be no nice
|
||||||
* way to sync on it. Hence we do the weak >= 2 check, even though == 2 is what we'd actually
|
* way to sync on it. Hence we do the weak >= 2 check, even though == 2 is what we'd actually
|
||||||
* like to check here */
|
* like to check here */
|
||||||
assert_se(get_process_threads(0) >= 2);
|
r = get_process_threads(0);
|
||||||
|
ASSERT_OK(r);
|
||||||
|
ASSERT_GE(r, 2);
|
||||||
|
|
||||||
assert_se(write(ppfd[1], &(const char) { 'x' }, 1) == 1);
|
ASSERT_OK_EQ_ERRNO(write(ppfd[1], &(const char) { 'x' }, 1), 1);
|
||||||
assert_se(pthread_join(tt, NULL) == 0);
|
ASSERT_OK_ZERO_ERRNO(pthread_join(tt, NULL));
|
||||||
|
|
||||||
/* similar here */
|
/* similar here */
|
||||||
assert_se(get_process_threads(0) >= 1);
|
r = get_process_threads(0);
|
||||||
|
ASSERT_OK(r);
|
||||||
|
ASSERT_GE(r, 1);
|
||||||
|
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
@ -902,17 +929,17 @@ TEST(get_process_threads) {
|
||||||
TEST(is_reaper_process) {
|
TEST(is_reaper_process) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = safe_fork("(regular)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_WAIT, NULL);
|
r = safe_fork("(regular)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_WAIT, NULL);
|
||||||
assert_se(r >= 0);
|
ASSERT_OK(r);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
/* child */
|
/* child */
|
||||||
|
|
||||||
assert_se(is_reaper_process() == 0);
|
ASSERT_OK_ZERO(is_reaper_process());
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = safe_fork("(newpid)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_WAIT, NULL);
|
r = safe_fork("(newpid)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_WAIT, NULL);
|
||||||
assert_se(r >= 0);
|
ASSERT_OK(r);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
/* child */
|
/* child */
|
||||||
|
|
||||||
|
@ -923,25 +950,25 @@ TEST(is_reaper_process) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r = safe_fork("(newpid1)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_WAIT, NULL);
|
r = safe_fork("(newpid1)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_WAIT, NULL);
|
||||||
assert_se(r >= 0);
|
ASSERT_OK(r);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
/* grandchild, which is PID1 in a pidns */
|
/* grandchild, which is PID1 in a pidns */
|
||||||
assert_se(getpid_cached() == 1);
|
ASSERT_OK_EQ(getpid_cached(), 1);
|
||||||
assert_se(is_reaper_process() > 0);
|
ASSERT_OK_POSITIVE(is_reaper_process());
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = safe_fork("(subreaper)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_WAIT, NULL);
|
r = safe_fork("(subreaper)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_WAIT, NULL);
|
||||||
assert_se(r >= 0);
|
ASSERT_OK(r);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
/* child */
|
/* child */
|
||||||
assert_se(make_reaper_process(true) >= 0);
|
ASSERT_OK(make_reaper_process(true));
|
||||||
|
|
||||||
assert_se(is_reaper_process() > 0);
|
ASSERT_OK_POSITIVE(is_reaper_process());
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -949,22 +976,22 @@ TEST(is_reaper_process) {
|
||||||
TEST(pid_get_start_time) {
|
TEST(pid_get_start_time) {
|
||||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
|
|
||||||
assert_se(pidref_set_self(&pidref) >= 0);
|
ASSERT_OK(pidref_set_self(&pidref));
|
||||||
|
|
||||||
usec_t start_time;
|
usec_t start_time;
|
||||||
assert_se(pidref_get_start_time(&pidref, &start_time) >= 0);
|
ASSERT_OK(pidref_get_start_time(&pidref, &start_time));
|
||||||
log_info("our starttime: " USEC_FMT, start_time);
|
log_info("our starttime: " USEC_FMT, start_time);
|
||||||
|
|
||||||
_cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
|
_cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
|
||||||
|
|
||||||
assert_se(pidref_safe_fork("(stub)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS, &child) >= 0);
|
ASSERT_OK(pidref_safe_fork("(stub)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG, &child));
|
||||||
|
|
||||||
usec_t start_time2;
|
usec_t start_time2;
|
||||||
assert_se(pidref_get_start_time(&child, &start_time2) >= 0);
|
ASSERT_OK(pidref_get_start_time(&child, &start_time2));
|
||||||
|
|
||||||
log_info("child starttime: " USEC_FMT, start_time2);
|
log_info("child starttime: " USEC_FMT, start_time2);
|
||||||
|
|
||||||
assert_se(start_time2 >= start_time);
|
ASSERT_GE(start_time2, start_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int intro(void) {
|
static int intro(void) {
|
||||||
|
|
|
@ -259,7 +259,7 @@ static int run(int argc, char *argv[]) {
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (arg_graceful && tpm2_support() != TPM2_SUPPORT_FULL) {
|
if (arg_graceful && !tpm2_is_fully_supported()) {
|
||||||
log_notice("No complete TPM2 support detected, exiting gracefully.");
|
log_notice("No complete TPM2 support detected, exiting gracefully.");
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -288,7 +288,7 @@ static int verb_info(int argc, char *argv[], void *userdata) {
|
||||||
pager_open(arg_pager_flags);
|
pager_open(arg_pager_flags);
|
||||||
|
|
||||||
if (FLAGS_SET(arg_json_format_flags, SD_JSON_FORMAT_OFF)) {
|
if (FLAGS_SET(arg_json_format_flags, SD_JSON_FORMAT_OFF)) {
|
||||||
static const struct sd_json_dispatch_field dispatch_table[] = {
|
static const sd_json_dispatch_field dispatch_table[] = {
|
||||||
{ "vendor", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(GetInfoData, vendor), SD_JSON_MANDATORY },
|
{ "vendor", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(GetInfoData, vendor), SD_JSON_MANDATORY },
|
||||||
{ "product", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(GetInfoData, product), SD_JSON_MANDATORY },
|
{ "product", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(GetInfoData, product), SD_JSON_MANDATORY },
|
||||||
{ "version", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(GetInfoData, version), SD_JSON_MANDATORY },
|
{ "version", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(GetInfoData, version), SD_JSON_MANDATORY },
|
||||||
|
@ -380,12 +380,12 @@ static int verb_introspect(int argc, char *argv[], void *userdata) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
const struct sd_json_dispatch_field dispatch_table[] = {
|
static const sd_json_dispatch_field dispatch_table[] = {
|
||||||
{ "interfaces", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_strv, PTR_TO_SIZE(&auto_interfaces), SD_JSON_MANDATORY },
|
{ "interfaces", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_strv, 0, SD_JSON_MANDATORY },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
r = sd_json_dispatch(reply, dispatch_table, SD_JSON_LOG|SD_JSON_ALLOW_EXTENSIONS, NULL);
|
r = sd_json_dispatch(reply, dispatch_table, SD_JSON_LOG|SD_JSON_ALLOW_EXTENSIONS, &auto_interfaces);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -412,7 +412,7 @@ static int verb_introspect(int argc, char *argv[], void *userdata) {
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (FLAGS_SET(arg_json_format_flags, SD_JSON_FORMAT_OFF) || list_methods) {
|
if (FLAGS_SET(arg_json_format_flags, SD_JSON_FORMAT_OFF) || list_methods) {
|
||||||
static const struct sd_json_dispatch_field dispatch_table[] = {
|
static const sd_json_dispatch_field dispatch_table[] = {
|
||||||
{ "description", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, 0, SD_JSON_MANDATORY },
|
{ "description", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, 0, SD_JSON_MANDATORY },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,5 +4,6 @@ integration_tests += [
|
||||||
integration_test_template + {
|
integration_test_template + {
|
||||||
'name' : fs.name(meson.current_source_dir()),
|
'name' : fs.name(meson.current_source_dir()),
|
||||||
'storage': 'persistent',
|
'storage': 'persistent',
|
||||||
|
'vm' : true,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
|
@ -21,6 +21,9 @@ at_exit() {
|
||||||
|
|
||||||
trap at_exit EXIT
|
trap at_exit EXIT
|
||||||
|
|
||||||
|
systemctl unmask systemd-networkd.service
|
||||||
|
systemctl start systemd-networkd.service
|
||||||
|
|
||||||
export NETWORK_NAME="10-networkctl-test-$RANDOM.network"
|
export NETWORK_NAME="10-networkctl-test-$RANDOM.network"
|
||||||
export NETDEV_NAME="10-networkctl-test-$RANDOM.netdev"
|
export NETDEV_NAME="10-networkctl-test-$RANDOM.netdev"
|
||||||
export LINK_NAME="10-networkctl-test-$RANDOM.link"
|
export LINK_NAME="10-networkctl-test-$RANDOM.link"
|
||||||
|
@ -75,15 +78,6 @@ cmp "+4" "/etc/systemd/network/${NETWORK_NAME}.d/test.conf"
|
||||||
networkctl cat "$NETWORK_NAME" | grep '^# ' |
|
networkctl cat "$NETWORK_NAME" | grep '^# ' |
|
||||||
cmp - <(printf '%s\n' "# /etc/systemd/network/$NETWORK_NAME" "# /etc/systemd/network/${NETWORK_NAME}.d/test.conf")
|
cmp - <(printf '%s\n' "# /etc/systemd/network/$NETWORK_NAME" "# /etc/systemd/network/${NETWORK_NAME}.d/test.conf")
|
||||||
|
|
||||||
networkctl edit --stdin --runtime "$NETDEV_NAME" <<EOF
|
|
||||||
[NetDev]
|
|
||||||
Name=test2
|
|
||||||
Kind=dummy
|
|
||||||
EOF
|
|
||||||
|
|
||||||
networkctl cat "$NETDEV_NAME" | grep -v '^# ' |
|
|
||||||
cmp - <(printf '%s\n' "[NetDev]" "Name=test2" "Kind=dummy")
|
|
||||||
|
|
||||||
cat >"/usr/lib/systemd/network/$LINK_NAME" <<EOF
|
cat >"/usr/lib/systemd/network/$LINK_NAME" <<EOF
|
||||||
[Match]
|
[Match]
|
||||||
OriginalName=test2
|
OriginalName=test2
|
||||||
|
@ -95,13 +89,23 @@ EOF
|
||||||
SYSTEMD_LOG_LEVEL=debug EDITOR='true' script -ec 'networkctl edit "$LINK_NAME"' /dev/null
|
SYSTEMD_LOG_LEVEL=debug EDITOR='true' script -ec 'networkctl edit "$LINK_NAME"' /dev/null
|
||||||
cmp "/usr/lib/systemd/network/$LINK_NAME" "/etc/systemd/network/$LINK_NAME"
|
cmp "/usr/lib/systemd/network/$LINK_NAME" "/etc/systemd/network/$LINK_NAME"
|
||||||
|
|
||||||
# Test links
|
# The interface test2 does not exist, hence the below do not work.
|
||||||
systemctl unmask systemd-networkd
|
|
||||||
systemctl stop systemd-networkd
|
|
||||||
(! networkctl cat @test2)
|
(! networkctl cat @test2)
|
||||||
(! networkctl cat @test2:netdev)
|
(! networkctl cat @test2:netdev)
|
||||||
|
(! networkctl cat @test2:link)
|
||||||
|
(! networkctl cat @test2:network)
|
||||||
|
|
||||||
systemctl start systemd-networkd
|
# create .netdev file at last, otherwise, the .link file will not be applied to the interface.
|
||||||
|
networkctl edit --stdin --runtime "$NETDEV_NAME" <<EOF
|
||||||
|
[NetDev]
|
||||||
|
Name=test2
|
||||||
|
Kind=dummy
|
||||||
|
EOF
|
||||||
|
|
||||||
|
networkctl cat "$NETDEV_NAME" | grep -v '^# ' |
|
||||||
|
cmp - <(printf '%s\n' "[NetDev]" "Name=test2" "Kind=dummy")
|
||||||
|
|
||||||
|
# wait for the interface being created and configured.
|
||||||
SYSTEMD_LOG_LEVEL=debug /usr/lib/systemd/systemd-networkd-wait-online -i test2:carrier --timeout 20
|
SYSTEMD_LOG_LEVEL=debug /usr/lib/systemd/systemd-networkd-wait-online -i test2:carrier --timeout 20
|
||||||
|
|
||||||
networkctl cat @test2:network | cmp - <(networkctl cat "$NETWORK_NAME")
|
networkctl cat @test2:network | cmp - <(networkctl cat "$NETWORK_NAME")
|
||||||
|
|
Loading…
Reference in New Issue