Compare commits

..

1 Commits

Author SHA1 Message Date
Muhammad Nuzaihan Bin Kamal Luddin a66b898d7a
Merge 5507ec986f into cd57920fbf 2024-09-19 01:17:44 +02:00
38 changed files with 801 additions and 729 deletions

View File

@ -962,9 +962,7 @@ default ignore - -</programlisting>
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
five lines indicating separately whether firmware, drivers, the system, the kernel and libraries
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>
discovered/support/use TPM2.</para>
<para>Note, this checks for TPM 2.0 devices only, and does not consider TPM 1.2 at all.</para>

View File

@ -29,7 +29,7 @@
<refsect1>
<title>Description</title>
<para><command>systemd-nsresourced</command> is a system service that permits transient delegation of a
<para><command>systemd-nsresourced</command> is a system service that permits transient delegation of a a
UID/GID range to a user namespace (see <citerefentry
project='man-pages'><refentrytitle>user_namespaces</refentrytitle><manvolnum>7</manvolnum></citerefentry>)
allocated by a client, via a Varlink IPC API.</para>

View File

@ -3,11 +3,18 @@
set -e
set -o nounset
if [[ "$DISTRIBUTION" =~ ubuntu|debian ]]; then
SUDO_GROUP=sudo
else
SUDO_GROUP=wheel
fi
useradd \
--uid 4711 \
--user-group \
--create-home \
--password "$(openssl passwd -1 testuser)" \
--groups "$SUDO_GROUP",systemd-journal \
--shell /bin/bash \
testuser

View File

@ -67,7 +67,7 @@ _systemd_analyze() {
)
local -A VERBS=(
[STANDALONE]='time blame unit-files unit-paths exit-status compare-versions calendar timestamp timespan pcrs srk has-tpm2'
[STANDALONE]='time blame unit-files unit-paths exit-status compare-versions calendar timestamp timespan pcrs srk'
[CRITICAL_CHAIN]='critical-chain'
[DOT]='dot'
[DUMP]='dump'

View File

@ -73,7 +73,6 @@ JSON or table format'
'timespan:Parse a systemd syntax timespan'
'security:Analyze security settings of a service'
'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
)

View File

@ -96,7 +96,7 @@ int verb_pcrs(int argc, char *argv[], void *userdata) {
const char *alg = NULL;
int r;
if (!tpm2_is_fully_supported())
if (tpm2_support() != TPM2_SUPPORT_FULL)
log_notice("System lacks full TPM2 support, not showing PCR state.");
else {
r = get_pcr_alg(&alg);

View File

@ -411,6 +411,7 @@ 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,
*current_entry = NULL, *oneshot_entry = NULL, *default_entry = NULL;
uint64_t loader_features = 0, stub_features = 0;
Tpm2Support s;
int have;
(void) efi_get_variable_string_and_warn(EFI_LOADER_VARIABLE(LoaderFirmwareType), &fw_type);
@ -439,7 +440,7 @@ int verb_status(int argc, char *argv[], void *userdata) {
else
printf("\n");
Tpm2Support s = tpm2_support_full(TPM2_SUPPORT_FIRMWARE|TPM2_SUPPORT_DRIVER);
s = tpm2_support();
printf(" TPM2 Support: %s%s%s\n",
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(),

View File

@ -450,7 +450,7 @@ static size_t pe_section_table_find_profile_length(
assert(start >= section_table);
assert(start < section_table + n_section_table);
/* Look for the next .profile (or the end of the table), this is where the sections for this
/* Look for the next .profile (or the end of the table), this is where the the sections for this
* profile end. The base profile does not start with a .profile, the others do, hence conditionally
* skip over the first entry. */
const PeSectionHeader *e;
@ -485,7 +485,7 @@ EFI_STATUS pe_locate_profile_sections(
if (!p)
return EFI_NOT_FOUND;
/* Look for the next .profile (or the end of the table), this is where the sections for this
/* Look for the next .profile (or the end of the table), this is where the the sections for this
* profile end. */
size_t n = pe_section_table_find_profile_length(section_table, n_section_table, p, profile);

View File

@ -1005,7 +1005,7 @@ static int validate_stub(void) {
bool found = false;
int r;
if (!tpm2_is_fully_supported())
if (tpm2_support() != TPM2_SUPPORT_FULL)
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Sorry, system lacks full TPM2 support.");
r = efi_stub_get_features(&features);

View File

@ -1229,7 +1229,7 @@ static int generic_method_get_interface_description(
sd_varlink_method_flags_t flags,
void *userdata) {
static const sd_json_dispatch_field dispatch_table[] = {
static const struct sd_json_dispatch_field dispatch_table[] = {
{ "interface", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, 0, SD_JSON_MANDATORY },
{}
};

View File

@ -416,18 +416,19 @@ 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 const sd_json_dispatch_field dispatch_table[] = {
{ "name", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, 0, 0 },
Manager *m = ASSERT_PTR(userdata);
const char *mn = NULL;
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;
assert(parameters);
r = sd_varlink_dispatch(link, parameters, dispatch_table, &mn);
r = sd_varlink_dispatch(link, parameters, dispatch_table, 0);
if (r != 0)
return r;

View File

@ -97,8 +97,8 @@ static int neighbor_append_json(Neighbor *n, sd_json_variant **array) {
return sd_json_variant_append_arraybo(
array,
SD_JSON_BUILD_PAIR_INTEGER("Family", n->dst_addr.family),
JSON_BUILD_PAIR_IN_ADDR("Destination", &n->dst_addr.address, n->dst_addr.family),
SD_JSON_BUILD_PAIR_INTEGER("Family", n->family),
JSON_BUILD_PAIR_IN_ADDR("Destination", &n->in_addr, n->family),
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("ConfigState", state));
@ -168,7 +168,7 @@ static int nexthop_append_json(NextHop *n, sd_json_variant **array) {
return sd_json_variant_append_arraybo(
array,
SD_JSON_BUILD_PAIR_UNSIGNED("ID", n->id),
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("Gateway", &n->gw.address, n->family),
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("Gateway", &n->gw, n->family),
SD_JSON_BUILD_PAIR_UNSIGNED("Flags", n->flags),
SD_JSON_BUILD_PAIR_STRING("FlagsString", strempty(flags)),
SD_JSON_BUILD_PAIR_UNSIGNED("Protocol", n->protocol),

View File

@ -147,29 +147,29 @@ static int neighbor_dup(const Neighbor *neighbor, Neighbor **ret) {
static void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state) {
assert(neighbor);
siphash24_compress_typesafe(neighbor->dst_addr.family, state);
siphash24_compress_typesafe(neighbor->family, state);
if (!IN_SET(neighbor->dst_addr.family, AF_INET, AF_INET6))
if (!IN_SET(neighbor->family, AF_INET, AF_INET6))
/* treat any other address family as AF_UNSPEC */
return;
/* Equality of neighbors are given by the destination address.
* See neigh_lookup() in the kernel. */
in_addr_hash_func(&neighbor->dst_addr.address, neighbor->dst_addr.family, state);
in_addr_hash_func(&neighbor->in_addr, neighbor->family, state);
}
static int neighbor_compare_func(const Neighbor *a, const Neighbor *b) {
int r;
r = CMP(a->dst_addr.family, b->dst_addr.family);
r = CMP(a->family, b->family);
if (r != 0)
return r;
if (!IN_SET(a->dst_addr.family, AF_INET, AF_INET6))
if (!IN_SET(a->family, AF_INET, AF_INET6))
/* treat any other address family as AF_UNSPEC */
return 0;
return memcmp(&a->dst_addr.address, &b->dst_addr.address, FAMILY_ADDRESS_SIZE(a->dst_addr.family));
return memcmp(&a->in_addr, &b->in_addr, FAMILY_ADDRESS_SIZE(a->family));
}
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",
str, strna(network_config_source_to_string(neighbor->source)), strna(state),
HW_ADDR_TO_STR(&neighbor->ll_addr),
IN_ADDR_TO_STRING(neighbor->dst_addr.family, &neighbor->dst_addr.address));
IN_ADDR_TO_STRING(neighbor->family, &neighbor->in_addr));
}
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);
r = sd_rtnl_message_new_neigh(link->manager->rtnl, &m, RTM_NEWNEIGH,
link->ifindex, neighbor->dst_addr.family);
link->ifindex, neighbor->family);
if (r < 0)
return r;
@ -273,7 +273,7 @@ static int neighbor_configure(Neighbor *neighbor, Link *link, Request *req) {
if (r < 0)
return r;
r = netlink_message_append_in_addr_union(m, NDA_DST, neighbor->dst_addr.family, &neighbor->dst_addr.address);
r = netlink_message_append_in_addr_union(m, NDA_DST, neighbor->family, &neighbor->in_addr);
if (r < 0)
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 hardware address length (%zu), ignoring the setting.",
neighbor->ll_addr.length,
IN_ADDR_TO_STRING(neighbor->dst_addr.family, &neighbor->dst_addr.address),
IN_ADDR_TO_STRING(neighbor->family, &neighbor->in_addr),
link->hw_addr.length);
return 0;
}
@ -451,11 +451,11 @@ int neighbor_remove(Neighbor *neighbor, Link *link) {
log_neighbor_debug(neighbor, "Removing", link);
r = sd_rtnl_message_new_neigh(link->manager->rtnl, &m, RTM_DELNEIGH,
link->ifindex, neighbor->dst_addr.family);
link->ifindex, neighbor->family);
if (r < 0)
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->dst_addr.family, &neighbor->dst_addr.address);
r = netlink_message_append_in_addr_union(m, NDA_DST, neighbor->family, &neighbor->in_addr);
if (r < 0)
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();
/* First, retrieve the fundamental information about the neighbor. */
r = sd_rtnl_message_neigh_get_family(message, &tmp->dst_addr.family);
r = sd_rtnl_message_neigh_get_family(message, &tmp->family);
if (r < 0) {
log_link_warning(link, "rtnl: received neighbor message without family, ignoring.");
return 0;
}
if (tmp->dst_addr.family == AF_BRIDGE) /* Currently, we do not support it. */
if (tmp->family == AF_BRIDGE) /* Currently, we do not support it. */
return 0;
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->dst_addr.family);
if (!IN_SET(tmp->family, AF_INET, AF_INET6)) {
log_link_debug(link, "rtnl: received neighbor message with invalid family '%i', ignoring.", tmp->family);
return 0;
}
r = netlink_message_read_in_addr_union(message, NDA_DST, tmp->dst_addr.family, &tmp->dst_addr.address);
r = netlink_message_read_in_addr_union(message, NDA_DST, tmp->family, &tmp->in_addr);
if (r < 0) {
log_link_warning_errno(link, r, "rtnl: received neighbor message without valid address, ignoring: %m");
return 0;
@ -660,28 +660,28 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message,
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) {
if (section_is_invalid(neighbor->section))
return -EINVAL;
if (neighbor->dst_addr.family == AF_UNSPEC)
return log_neighbor_section(neighbor, "Neighbor section without Address= configured.");
if (neighbor->family == AF_UNSPEC)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: Neighbor section without Address= configured. "
"Ignoring [Neighbor] section from line %u.",
neighbor->section->filename, neighbor->section->line);
if (neighbor->dst_addr.family == AF_INET6 && !socket_ipv6_is_supported())
return log_neighbor_section(neighbor, "Neighbor section with an IPv6 destination address configured, but the kernel does not support IPv6.");
if (neighbor->family == AF_INET6 && !socket_ipv6_is_supported())
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%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)
return log_neighbor_section(neighbor, "Neighbor section without LinkLayerAddress= configured.");
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: Neighbor section without LinkLayerAddress= configured. "
"Ignoring [Neighbor] section from line %u.",
neighbor->section->filename, neighbor->section->line);
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, "
"dropping the neighbor setting specified at line %u.",
dup->section->filename,
IN_ADDR_TO_STRING(neighbor->dst_addr.family, &neighbor->dst_addr.address),
IN_ADDR_TO_STRING(neighbor->family, &neighbor->in_addr),
neighbor->section->line,
dup->section->line, dup->section->line);
/* 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_section(
int config_parse_neighbor_address(
const char *unit,
const char *filename,
unsigned line,
@ -740,26 +740,76 @@ int config_parse_neighbor_section(
void *data,
void *userdata) {
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;
_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, &neighbor);
r = neighbor_new_static(network, filename, section_line, &n);
if (r < 0)
return log_oom();
r = config_section_parse(table, ELEMENTSOF(table),
unit, filename, line, section, section_line, lvalue, ltype, rvalue, neighbor);
if (r <= 0) /* 0 means non-critical error, but the section will be ignored. */
return r;
if (isempty(rvalue)) {
n->family = AF_UNSPEC;
n->in_addr = IN_ADDR_NULL;
TAKE_PTR(n);
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;
}

View File

@ -23,7 +23,8 @@ typedef struct Neighbor {
unsigned n_ref;
struct in_addr_data dst_addr;
int family;
union in_addr_union in_addr;
struct hw_addr_data ll_addr;
} Neighbor;
@ -45,11 +46,5 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message,
DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(Neighbor, neighbor);
typedef enum NeighborConfParserType {
NEIGHBOR_DESTINATION_ADDRESS,
NEIGHBOR_LINK_LAYER_ADDRESS,
_NEIGHBOR_CONF_PARSER_MAX,
_NEIGHBOR_CONF_PARSER_INVALID = -EINVAL,
} NeighborConfParserType;
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_section);
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_address);
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_lladdr);

View File

@ -173,9 +173,9 @@ Address.NetLabel, config_parse_address_section,
Address.NFTSet, config_parse_address_section, ADDRESS_NFT_SET, 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
Neighbor.Address, config_parse_neighbor_section, NEIGHBOR_DESTINATION_ADDRESS, 0
Neighbor.LinkLayerAddress, config_parse_neighbor_section, NEIGHBOR_LINK_LAYER_ADDRESS, 0
Neighbor.MACAddress, config_parse_neighbor_section, NEIGHBOR_LINK_LAYER_ADDRESS, 0 /* deprecated */
Neighbor.Address, config_parse_neighbor_address, 0, 0
Neighbor.LinkLayerAddress, config_parse_neighbor_lladdr, 0, 0
Neighbor.MACAddress, config_parse_neighbor_lladdr, 0, 0 /* deprecated */
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.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.FastOpenNoCookie, config_parse_route_metric_boolean, RTAX_FASTOPEN_NO_COOKIE, 0
Route.TTLPropagate, config_parse_warn_compat, DISABLED_LEGACY, 0
NextHop.Id, config_parse_nexthop_section, NEXTHOP_ID, 0
NextHop.Gateway, config_parse_nexthop_section, NEXTHOP_GATEWAY, 0
NextHop.Family, config_parse_nexthop_section, NEXTHOP_FAMILY, 0
NextHop.OnLink, config_parse_nexthop_section, NEXTHOP_ONLINK, 0
NextHop.Blackhole, config_parse_nexthop_section, NEXTHOP_BLACKHOLE, 0
NextHop.Group, config_parse_nexthop_section, NEXTHOP_GROUP, 0
NextHop.Id, config_parse_nexthop_id, 0, 0
NextHop.Gateway, config_parse_nexthop_gateway, 0, 0
NextHop.Family, config_parse_nexthop_family, 0, 0
NextHop.OnLink, config_parse_nexthop_onlink, 0, 0
NextHop.Blackhole, config_parse_nexthop_blackhole, 0, 0
NextHop.Group, config_parse_nexthop_group, 0, 0
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.UseDNS, config_parse_tristate, 0, offsetof(Network, dhcp_use_dns)

View File

@ -854,7 +854,7 @@ bool network_has_static_ipv6_configurations(Network *network) {
return true;
ORDERED_HASHMAP_FOREACH(neighbor, network->neighbors_by_section)
if (neighbor->dst_addr.family == AF_INET6)
if (neighbor->family == AF_INET6)
return true;
if (!hashmap_isempty(network->address_labels_by_section))

View File

@ -236,7 +236,7 @@ static int nexthop_compare_full(const NextHop *a, const NextHop *b) {
return r;
if (IN_SET(a->family, AF_INET, AF_INET6)) {
r = memcmp(&a->gw.address, &b->gw.address, FAMILY_ADDRESS_SIZE(a->family));
r = memcmp(&a->gw, &b->gw, FAMILY_ADDRESS_SIZE(a->family));
if (r != 0)
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",
str, strna(network_config_source_to_string(nexthop->source)), strna(state),
nexthop->id,
IN_ADDR_TO_STRING(nexthop->family, &nexthop->gw.address),
IN_ADDR_TO_STRING(nexthop->family, &nexthop->gw),
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)
return r;
if (in_addr_is_set(nexthop->family, &nexthop->gw.address)) {
r = netlink_message_append_in_addr_union(m, NHA_GATEWAY, nexthop->family, &nexthop->gw.address);
if (in_addr_is_set(nexthop->family, &nexthop->gw)) {
r = netlink_message_append_in_addr_union(m, NHA_GATEWAY, nexthop->family, &nexthop->gw);
if (r < 0)
return r;
@ -722,7 +722,7 @@ static bool nexthop_is_ready_to_configure(Link *link, const NextHop *nexthop) {
return r;
}
return gateway_is_ready(link, FLAGS_SET(nexthop->flags, RTNH_F_ONLINK), nexthop->family, &nexthop->gw.address);
return gateway_is_ready(link, FLAGS_SET(nexthop->flags, RTNH_F_ONLINK), nexthop->family, &nexthop->gw);
}
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);
if (nexthop->family != AF_UNSPEC) {
r = netlink_message_read_in_addr_union(message, NHA_GATEWAY, nexthop->family, &nexthop->gw.address);
r = netlink_message_read_in_addr_union(message, NHA_GATEWAY, nexthop->family, &nexthop->gw);
if (r == -ENODATA)
nexthop->gw.address = IN_ADDR_NULL;
nexthop->gw = IN_ADDR_NULL;
else if (r < 0)
log_debug_errno(r, "rtnl: could not get NHA_GATEWAY attribute, ignoring: %m");
}
@ -1129,60 +1129,66 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message,
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) {
if (section_is_invalid(nh->section))
return -EINVAL;
if (!nh->network->manager->manage_foreign_nexthops && nh->id == 0)
return log_nexthop_section(nh, "Nexthop without specifying Id= is not supported if ManageForeignNextHops=no is set in networkd.conf.");
if (nh->family == AF_UNSPEC)
nh->family = nh->gw.family;
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);
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: [NextHop] section without specifying Id= is not supported "
"if ManageForeignNextHops=no is set in networkd.conf. "
"Ignoring [NextHop] section from line %u.",
nh->section->filename, nh->section->line);
if (!hashmap_isempty(nh->group)) {
if (in_addr_is_set(nh->family, &nh->gw.address))
return log_nexthop_section(nh, "Nexthop group cannot have gateway address.");
if (in_addr_is_set(nh->family, &nh->gw))
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: nexthop group cannot have gateway address. "
"Ignoring [NextHop] section from line %u.",
nh->section->filename, nh->section->line);
if (nh->family != AF_UNSPEC)
return log_nexthop_section(nh, "Nexthop group cannot have Family= setting.");
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: nexthop group cannot have Family= setting. "
"Ignoring [NextHop] section from line %u.",
nh->section->filename, nh->section->line);
if (nh->blackhole)
return log_nexthop_section(nh, "Nexthop group cannot be a blackhole.");
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: nexthop group cannot be a blackhole. "
"Ignoring [NextHop] section from line %u.",
nh->section->filename, nh->section->line);
if (nh->onlink > 0)
return log_nexthop_section(nh, "Nexthop group cannot have on-link flag.");
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%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)
/* When neither Family=, Gateway=, nor Group= is specified, assume IPv4. */
nh->family = AF_INET;
if (nh->blackhole) {
if (in_addr_is_set(nh->family, &nh->gw.address))
return log_nexthop_section(nh, "Blackhole nexthop cannot have gateway address.");
if (in_addr_is_set(nh->family, &nh->gw))
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: blackhole nexthop cannot have gateway address. "
"Ignoring [NextHop] section from line %u.",
nh->section->filename, nh->section->line);
if (nh->onlink > 0)
return log_nexthop_section(nh, "Blackhole nexthop cannot have on-link flag.");
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%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.address) &&
if (nh->onlink < 0 && in_addr_is_set(nh->family, &nh->gw) &&
ordered_hashmap_isempty(nh->network->addresses_by_section)) {
/* If no address is configured, in most cases the gateway cannot be reachable.
* TODO: we may need to improve the condition above. */
log_section_warning(nh->section, "Nexthop with Gateway= specified, but no static address configured. Enabling OnLink= option.");
log_warning("%s: Gateway= without static address configured. "
"Enabling OnLink= option.",
nh->section->filename);
nh->onlink = true;
}
@ -1256,7 +1262,7 @@ int manager_build_nexthop_ids(Manager *manager) {
return 0;
}
static int config_parse_nexthop_family(
int config_parse_nexthop_id(
const char *unit,
const char *filename,
unsigned line,
@ -1268,38 +1274,261 @@ static int config_parse_nexthop_family(
void *data,
void *userdata) {
int *family = ASSERT_PTR(data);
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);
_cleanup_(nexthop_unref_or_set_invalidp) NextHop *n = NULL;
Network *network = userdata;
uint32_t id;
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)) {
*group = hashmap_free_free(*group);
return 1;
n->id = 0;
TAKE_PTR(n);
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;;) {
@ -1309,10 +1538,15 @@ static int config_parse_nexthop_group(
char *sep;
r = extract_first_word(&p, &word, NULL, 0);
if (r < 0)
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid %s=, ignoring assignment: %s", lvalue, rvalue);
return 0;
}
if (r == 0)
return 1;
break;
nhg = new0(struct nexthop_grp, 1);
if (!nhg)
@ -1352,7 +1586,7 @@ static int config_parse_nexthop_group(
continue;
}
r = hashmap_ensure_put(group, NULL, UINT32_TO_PTR(nhg->id), nhg);
r = hashmap_ensure_put(&n->group, NULL, UINT32_TO_PTR(nhg->id), nhg);
if (r == -ENOMEM)
return log_oom();
if (r == -EEXIST) {
@ -1364,44 +1598,7 @@ static int config_parse_nexthop_group(
assert(r > 0);
TAKE_PTR(nhg);
}
}
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);
TAKE_PTR(n);
return 0;
}

View File

@ -36,7 +36,7 @@ typedef struct NextHop {
Hashmap *group; /* NHA_GROUP */
bool blackhole; /* NHA_BLACKHOLE */
int ifindex; /* NHA_OIF */
struct in_addr_data gw; /* NHA_GATEWAY, gw.family is only used by conf parser. */
union in_addr_union gw; /* NHA_GATEWAY */
/* Only used in conf parser and nexthop_section_verify(). */
int onlink;
@ -71,15 +71,9 @@ int manager_build_nexthop_ids(Manager *manager);
DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(NextHop, nexthop);
typedef enum NextHopConfParserType {
NEXTHOP_ID,
NEXTHOP_GATEWAY,
NEXTHOP_FAMILY,
NEXTHOP_ONLINK,
NEXTHOP_BLACKHOLE,
NEXTHOP_GROUP,
_NEXTHOP_CONF_PARSER_MAX,
_NEXTHOP_CONF_PARSER_INVALID = -EINVAL,
} NextHopConfParserType;
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_section);
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_id);
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_gateway);
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_family);
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_onlink);
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_blackhole);
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_group);

View File

@ -1742,7 +1742,7 @@ static int oci_seccomp_args(const char *name, sd_json_variant *v, sd_json_dispat
int r;
JSON_VARIANT_ARRAY_FOREACH(e, v) {
static const sd_json_dispatch_field table[] = {
static const struct sd_json_dispatch_field table[] = {
{ "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 },
{ "valueTwo", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint64, offsetof(struct scmp_arg_cmp, datum_b), 0 },

View File

@ -369,7 +369,7 @@ static int run(int argc, char *argv[]) {
event = TPM2_EVENT_PHASE;
}
if (arg_graceful && !tpm2_is_fully_supported()) {
if (arg_graceful && tpm2_support() != TPM2_SUPPORT_FULL) {
log_notice("No complete TPM2 support detected, exiting gracefully.");
return EXIT_SUCCESS;
}

View File

@ -2876,76 +2876,55 @@ static int print_answer(sd_json_variant *answer) {
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 const sd_json_dispatch_field dispatch_table[] = {
{ "question", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_variant, offsetof(MonitorQueryParams, question), SD_JSON_MANDATORY },
{ "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 },
{ "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 },
{ "rcode", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int, offsetof(MonitorQueryParams, rcode), 0 },
{ "errno", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int, offsetof(MonitorQueryParams, error), 0 },
{ "extendedDNSErrorCode", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int, offsetof(MonitorQueryParams, ede_code), 0 },
{ "extendedDNSErrorMessage", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(MonitorQueryParams, ede_msg), 0 },
{}
};
_cleanup_(monitor_query_params_done) MonitorQueryParams p = {
.rcode = -1,
.ede_code = -1,
};
_cleanup_(sd_json_variant_unrefp) sd_json_variant *question = NULL, *answer = NULL, *collected_questions = NULL;
int rcode = -1, error = 0, ede_code = -1;
const char *state = NULL, *result = NULL, *ede_msg = NULL;
assert(v);
if (sd_json_dispatch(v, dispatch_table, SD_JSON_LOG|SD_JSON_ALLOW_EXTENSIONS, &p) < 0)
sd_json_dispatch_field dispatch_table[] = {
{ "question", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_variant, PTR_TO_SIZE(&question), SD_JSON_MANDATORY },
{ "answer", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_variant, PTR_TO_SIZE(&answer), 0 },
{ "collectedQuestions", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_variant, PTR_TO_SIZE(&collected_questions), 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)
return;
/* First show the current question */
print_question('Q', ansi_highlight_cyan(), p.question);
print_question('Q', ansi_highlight_cyan(), question);
/* And then show the questions that led to this one in case this was a CNAME chain */
print_question('C', ansi_highlight_grey(), p.collected_questions);
print_question('C', ansi_highlight_grey(), collected_questions);
printf("%s%s S%s: %s",
streq_ptr(p.state, "success") ? ansi_highlight_green() : ansi_highlight_red(),
streq_ptr(state, "success") ? ansi_highlight_green() : ansi_highlight_red(),
special_glyph(SPECIAL_GLYPH_ARROW_LEFT),
ansi_normal(),
strna(streq_ptr(p.state, "errno") ? errno_to_name(p.error) :
streq_ptr(p.state, "rcode-failure") ? dns_rcode_to_string(p.rcode) :
p.state));
strna(streq_ptr(state, "errno") ? errno_to_name(error) :
streq_ptr(state, "rcode-failure") ? dns_rcode_to_string(rcode) :
state));
if (!isempty(p.result))
printf(": %s", p.result);
if (!isempty(result))
printf(": %s", result);
if (p.ede_code >= 0)
if (ede_code >= 0)
printf(" (%s%s%s)",
FORMAT_DNS_EDE_RCODE(p.ede_code),
!isempty(p.ede_msg) ? ": " : "",
strempty(p.ede_msg));
FORMAT_DNS_EDE_RCODE(ede_code),
!isempty(ede_msg) ? ": " : "",
strempty(ede_msg));
puts("");
print_answer(p.answer);
print_answer(answer);
}
static int monitor_reply(

View File

@ -2145,31 +2145,26 @@ int dns_resource_key_to_json(DnsResourceKey *key, sd_json_variant **ret) {
}
int dns_resource_key_from_json(sd_json_variant *v, DnsResourceKey **ret) {
struct params {
uint16_t type;
uint16_t class;
const char *name;
};
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
uint16_t type = 0, class = 0;
const char *name = NULL;
int r;
static const sd_json_dispatch_field dispatch_table[] = {
{ "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, offsetof(struct params, type), SD_JSON_MANDATORY },
{ "name", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(struct params, name), SD_JSON_MANDATORY },
sd_json_dispatch_field dispatch_table[] = {
{ "class", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint16, PTR_TO_SIZE(&class), SD_JSON_MANDATORY },
{ "type", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint16, PTR_TO_SIZE(&type), SD_JSON_MANDATORY },
{ "name", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, PTR_TO_SIZE(&name), SD_JSON_MANDATORY },
{}
};
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
struct params p;
int r;
assert(v);
assert(ret);
r = sd_json_dispatch(v, dispatch_table, 0, &p);
r = sd_json_dispatch(v, dispatch_table, 0, NULL);
if (r < 0)
return r;
key = dns_resource_key_new(p.class, p.type, p.name);
key = dns_resource_key_new(class, type, name);
if (!key)
return -ENOMEM;

View File

@ -667,7 +667,7 @@ static int has_tpm2(void) {
*
* Note that we don't check if we ourselves are built with TPM2 support here! */
return FLAGS_SET(tpm2_support_full(TPM2_SUPPORT_SUBSYSTEM|TPM2_SUPPORT_FIRMWARE), TPM2_SUPPORT_SUBSYSTEM|TPM2_SUPPORT_FIRMWARE);
return FLAGS_SET(tpm2_support(), TPM2_SUPPORT_SUBSYSTEM|TPM2_SUPPORT_FIRMWARE);
}
static int condition_test_security(Condition *c, char **env) {

View File

@ -1764,7 +1764,7 @@ int config_parse_hw_addr(
void *data,
void *userdata) {
struct hw_addr_data *hwaddr = ASSERT_PTR(data);
struct hw_addr_data a, *hwaddr = ASSERT_PTR(data);
int r;
assert(filename);
@ -1776,10 +1776,11 @@ int config_parse_hw_addr(
return 1;
}
r = parse_hw_addr_full(rvalue, ltype, hwaddr);
r = parse_hw_addr_full(rvalue, ltype, &a);
if (r < 0)
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
*hwaddr = a;
return 1;
}
@ -1972,36 +1973,6 @@ int config_parse_in_addr_non_null(
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(
const char *unit,
const char *filename,

View File

@ -305,7 +305,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_hw_addrs);
CONFIG_PARSER_PROTOTYPE(config_parse_ether_addr);
CONFIG_PARSER_PROTOTYPE(config_parse_ether_addrs);
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_permyriad);
CONFIG_PARSER_PROTOTYPE(config_parse_pid);

View File

@ -886,7 +886,7 @@ int encrypt_credential_and_warn(
* 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. */
try_tpm2 = tpm2_is_fully_supported();
try_tpm2 = tpm2_support() == TPM2_SUPPORT_FULL;
if (!try_tpm2)
log_debug("System lacks TPM2 support or running in a container, not attempting to use TPM2.");
} else
@ -1582,12 +1582,14 @@ 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);
}
static const sd_json_dispatch_field dispatch_table[] = {
{ "blob", SD_JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, 0, SD_JSON_MANDATORY },
r = sd_json_dispatch(
reply,
(const sd_json_dispatch_field[]) {
{ "blob", SD_JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, PTR_TO_SIZE(ret), SD_JSON_MANDATORY },
{},
};
r = sd_json_dispatch(reply, dispatch_table, SD_JSON_LOG|SD_JSON_ALLOW_EXTENSIONS, ret);
},
SD_JSON_LOG|SD_JSON_ALLOW_EXTENSIONS,
/* userdata= */ NULL);
if (r < 0)
return r;
@ -1647,12 +1649,14 @@ 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);
}
static const sd_json_dispatch_field dispatch_table[] = {
{ "data", SD_JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, 0, SD_JSON_MANDATORY },
r = sd_json_dispatch(
reply,
(const sd_json_dispatch_field[]) {
{ "data", SD_JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, PTR_TO_SIZE(ret), SD_JSON_MANDATORY },
{},
};
r = sd_json_dispatch(reply, dispatch_table, SD_JSON_LOG|SD_JSON_ALLOW_EXTENSIONS, ret);
},
SD_JSON_LOG|SD_JSON_ALLOW_EXTENSIONS,
/* userdata= */ NULL);
if (r < 0)
return r;

View File

@ -250,18 +250,6 @@ int nsresource_add_cgroup(int userns_fd, int cgroup_fd) {
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 userns_fd,
int netns_fd,
@ -325,20 +313,20 @@ int nsresource_add_netif(
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);
static const sd_json_dispatch_field dispatch_table[] = {
{ "hostInterfaceName", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(InterfaceParams, host_interface_name), 0 },
{ "namespaceInterfaceName", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(InterfaceParams, namespace_interface_name), 0 },
};
_cleanup_(interface_params_done) InterfaceParams p = {};
r = sd_json_dispatch(reply, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, &p);
if (r < 0)
return r;
_cleanup_free_ char *host_interface_name = NULL, *namespace_interface_name = NULL;
r = sd_json_dispatch(
reply,
(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) },
},
SD_JSON_ALLOW_EXTENSIONS,
/* userdata= */ NULL);
if (ret_host_ifname)
*ret_host_ifname = TAKE_PTR(p.host_interface_name);
*ret_host_ifname = TAKE_PTR(host_interface_name);
if (ret_namespace_ifname)
*ret_namespace_ifname = TAKE_PTR(p.namespace_interface_name);
*ret_namespace_ifname = TAKE_PTR(namespace_interface_name);
return 1;
}

View File

@ -281,44 +281,6 @@ 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) \
({ \
typeof(expr) _result = (expr); \

View File

@ -3,7 +3,6 @@
#include <sys/file.h>
#include "alloc-util.h"
#include "ansi-color.h"
#include "constants.h"
#include "creds-util.h"
#include "cryptsetup-util.h"
@ -7873,11 +7872,11 @@ int tpm2_sym_mode_from_string(const char *mode) {
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown symmetric mode name '%s'", mode);
}
Tpm2Support tpm2_support_full(Tpm2Support mask) {
Tpm2Support tpm2_support(void) {
Tpm2Support support = TPM2_SUPPORT_NONE;
int r;
if (((mask & (TPM2_SUPPORT_SUBSYSTEM|TPM2_SUPPORT_DRIVER)) != 0) && detect_container() <= 0) {
if (detect_container() <= 0) {
/* 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,
* let's assume containers never have a TPM, at least for now. */
@ -7894,24 +7893,18 @@ Tpm2Support tpm2_support_full(Tpm2Support mask) {
support |= TPM2_SUPPORT_SUBSYSTEM;
}
if (FLAGS_SET(mask, TPM2_SUPPORT_FIRMWARE) && efi_has_tpm2())
if (efi_has_tpm2())
support |= TPM2_SUPPORT_FIRMWARE;
#if HAVE_TPM2
support |= TPM2_SUPPORT_SYSTEM;
if (FLAGS_SET(mask, TPM2_SUPPORT_LIBRARIES)) {
r = dlopen_tpm2();
if (r >= 0)
support |= TPM2_SUPPORT_LIBRARIES;
}
#endif
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());
return support;
}
int verb_has_tpm2_generic(bool quiet) {
@ -7921,17 +7914,22 @@ int verb_has_tpm2_generic(bool quiet) {
if (!quiet) {
if (s == TPM2_SUPPORT_FULL)
printf("%syes%s\n", ansi_green(), ansi_normal());
puts("yes");
else if (s == TPM2_SUPPORT_NONE)
printf("%sno%s\n", ansi_red(), ansi_normal());
puts("no");
else
printf("%spartial%s\n", ansi_yellow(), ansi_normal());
puts("partial");
print_field("firmware", FLAGS_SET(s, TPM2_SUPPORT_FIRMWARE));
print_field("driver", FLAGS_SET(s, TPM2_SUPPORT_DRIVER));
print_field("system", FLAGS_SET(s, TPM2_SUPPORT_SYSTEM));
print_field("subsystem", FLAGS_SET(s, TPM2_SUPPORT_SUBSYSTEM));
print_field("libraries", FLAGS_SET(s, TPM2_SUPPORT_LIBRARIES));
printf("%sfirmware\n"
"%sdriver\n"
"%ssystem\n"
"%ssubsystem\n"
"%slibraries\n",
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

View File

@ -450,8 +450,8 @@ typedef struct {
} systemd_tpm2_plugin_params;
typedef enum Tpm2Support {
/* NOTE! The systemd-analyze has-tpm2 command returns these flags 1:1 as exit status. Hence these
* flags are pretty much ABI! Hence, be extra careful when changing/extending these definitions. */
/* NOTE! The systemd-creds tool returns these flags 1:1 as exit status. Hence these flags are pretty
* much ABI! Hence, be extra careful when changing/extending these definitions. */
TPM2_SUPPORT_NONE = 0, /* no support */
TPM2_SUPPORT_FIRMWARE = 1 << 0, /* firmware reports TPM2 was used */
TPM2_SUPPORT_DRIVER = 1 << 1, /* the kernel has a driver loaded for it */
@ -461,13 +461,7 @@ typedef enum Tpm2Support {
TPM2_SUPPORT_FULL = TPM2_SUPPORT_FIRMWARE|TPM2_SUPPORT_DRIVER|TPM2_SUPPORT_SYSTEM|TPM2_SUPPORT_SUBSYSTEM|TPM2_SUPPORT_LIBRARIES,
} Tpm2Support;
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;
}
Tpm2Support tpm2_support(void);
int verb_has_tpm2_generic(bool quiet);

View File

@ -161,12 +161,12 @@ static int process_machine(const char *machine, const char *port) {
uint32_t cid = VMADDR_CID_ANY;
static const sd_json_dispatch_field dispatch_table[] = {
{ "vSockCid", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint32, 0, 0 },
const sd_json_dispatch_field dispatch_table[] = {
{ "vSockCid", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint32, PTR_TO_SIZE(&cid), 0 },
{}
};
r = sd_json_dispatch(result, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, &cid);
r = sd_json_dispatch(result, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, NULL);
if (r < 0)
return log_error_errno(r, "Failed to parse Varlink reply: %m");

View File

@ -321,27 +321,12 @@ static int list_targets(sd_bus *bus) {
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) {
Version v = {};
char *version_json = NULL;
_cleanup_(sd_json_variant_unrefp) sd_json_variant *json = NULL;
_cleanup_(sd_json_variant_unrefp) sd_json_variant *json = NULL, *contents_json = NULL;
bool newest = false, available = false, installed = false, obsolete = false, protected = false,
incomplete = false;
int r;
assert(reply);
@ -357,37 +342,36 @@ static int parse_describe(sd_bus_message *reply, Version *ret) {
assert(sd_json_variant_is_object(json));
static const sd_json_dispatch_field dispatch_table[] = {
{ "version", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(DescribeParams, v.version), 0 },
{ "newest", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(DescribeParams, newest), 0 },
{ "available", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(DescribeParams, available), 0 },
{ "installed", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(DescribeParams, installed), 0 },
{ "obsolete", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(DescribeParams, obsolete), 0 },
{ "protected", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(DescribeParams, protected), 0 },
{ "incomplete", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(DescribeParams, incomplete), 0 },
{ "changelog_urls", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_strv, offsetof(DescribeParams, v.changelog), 0 },
{ "contents", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_variant, offsetof(DescribeParams, contents_json), 0 },
r = sd_json_dispatch(json,
(const sd_json_dispatch_field[]) {
{ "version", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, PTR_TO_SIZE(&v.version), 0 },
{ "newest", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, PTR_TO_SIZE(&newest), 0 },
{ "available", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, PTR_TO_SIZE(&available), 0 },
{ "installed", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, PTR_TO_SIZE(&installed), 0 },
{ "obsolete", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, PTR_TO_SIZE(&obsolete), 0 },
{ "protected", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, PTR_TO_SIZE(&protected), 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, PTR_TO_SIZE(&v.changelog), 0 },
{ "contents", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_variant, PTR_TO_SIZE(&contents_json), 0 },
{},
};
_cleanup_(describe_params_done) DescribeParams p = {};
r = sd_json_dispatch(json, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, &p);
},
SD_JSON_ALLOW_EXTENSIONS,
/* userdata= */ NULL);
if (r < 0)
return log_error_errno(r, "Failed to parse JSON: %m");
SET_FLAG(p.v.flags, UPDATE_NEWEST, p.newest);
SET_FLAG(p.v.flags, UPDATE_AVAILABLE, p.available);
SET_FLAG(p.v.flags, UPDATE_INSTALLED, p.installed);
SET_FLAG(p.v.flags, UPDATE_OBSOLETE, p.obsolete);
SET_FLAG(p.v.flags, UPDATE_PROTECTED, p.protected);
SET_FLAG(p.v.flags, UPDATE_INCOMPLETE, p.incomplete);
SET_FLAG(v.flags, UPDATE_NEWEST, newest);
SET_FLAG(v.flags, UPDATE_AVAILABLE, available);
SET_FLAG(v.flags, UPDATE_INSTALLED, installed);
SET_FLAG(v.flags, UPDATE_OBSOLETE, obsolete);
SET_FLAG(v.flags, UPDATE_PROTECTED, protected);
SET_FLAG(v.flags, UPDATE_INCOMPLETE, incomplete);
r = sd_json_variant_format(p.contents_json, 0, &p.v.contents_json);
r = sd_json_variant_format(contents_json, 0, &v.contents_json);
if (r < 0)
return log_error_errno(r, "Failed to format JSON for contents: %m");
*ret = TAKE_STRUCT(p.v);
*ret = TAKE_STRUCT(v);
return 0;
}

View File

@ -1141,18 +1141,6 @@ TEST(ASSERT) {
ASSERT_SIGNAL(ASSERT_OK_ERRNO(-1), 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(-EPERM);
ASSERT_SIGNAL(ASSERT_FAIL(0), SIGABRT);

View File

@ -54,51 +54,46 @@ static void test_pid_get_comm_one(pid_t pid) {
xsprintf(path, "/proc/"PID_FMT"/comm", pid);
if (stat(path, &st) == 0) {
ASSERT_OK(pid_get_comm(pid, &a));
assert_se(pid_get_comm(pid, &a) >= 0);
log_info("PID"PID_FMT" comm: '%s'", pid, a);
} else
log_warning("%s not exist.", path);
ASSERT_OK(pid_get_cmdline(pid, 0, PROCESS_CMDLINE_COMM_FALLBACK, &c));
assert_se(pid_get_cmdline(pid, 0, PROCESS_CMDLINE_COMM_FALLBACK, &c) >= 0);
log_info("PID"PID_FMT" cmdline: '%s'", pid, c);
ASSERT_OK(pid_get_cmdline(pid, 8, 0, &d));
assert_se(pid_get_cmdline(pid, 8, 0, &d) >= 0);
log_info("PID"PID_FMT" cmdline truncated to 8: '%s'", pid, d);
free(d);
ASSERT_OK(pid_get_cmdline(pid, 1, 0, &d));
assert_se(pid_get_cmdline(pid, 1, 0, &d) >= 0);
log_info("PID"PID_FMT" cmdline truncated to 1: '%s'", pid, d);
r = get_process_ppid(pid, &e);
if (pid == 1)
ASSERT_ERROR(r, EADDRNOTAVAIL);
else
ASSERT_OK(r);
assert_se(pid == 1 ? r == -EADDRNOTAVAIL : r >= 0);
if (r >= 0) {
log_info("PID"PID_FMT" PPID: "PID_FMT, pid, e);
ASSERT_GT(e, 0);
assert_se(e > 0);
}
ASSERT_TRUE(pid_is_kernel_thread(pid) == 0 || pid != 1);
assert_se(pid_is_kernel_thread(pid) == 0 || pid != 1);
r = get_process_exe(pid, &f);
if (r != -EACCES)
ASSERT_OK(r);
assert_se(r >= 0 || r == -EACCES);
log_info("PID"PID_FMT" exe: '%s'", pid, strna(f));
ASSERT_OK_ZERO(pid_get_uid(pid, &u));
assert_se(pid_get_uid(pid, &u) == 0);
log_info("PID"PID_FMT" UID: "UID_FMT, pid, u);
ASSERT_OK_ZERO(get_process_gid(pid, &g));
assert_se(get_process_gid(pid, &g) == 0);
log_info("PID"PID_FMT" GID: "GID_FMT, pid, g);
r = get_process_environ(pid, &env);
if (r != -EACCES)
ASSERT_OK(r);
assert_se(r >= 0 || r == -EACCES);
log_info("PID"PID_FMT" strlen(environ): %zi", pid, env ? (ssize_t)strlen(env) : (ssize_t)-errno);
if (!detect_container() && pid == 1)
ASSERT_ERROR(get_ctty_devnr(pid, &h), ENXIO);
if (!detect_container())
assert_se(get_ctty_devnr(pid, &h) == -ENXIO || pid != 1);
(void) getenv_for_pid(pid, "PATH", &i);
log_info("PID"PID_FMT" $PATH: '%s'", pid, strna(i));
@ -141,14 +136,14 @@ static void test_pid_get_cmdline_one(pid_t pid) {
r = pid_get_cmdline_strv(pid, 0, &strv_a);
if (r >= 0)
ASSERT_NOT_NULL(joined = strv_join(strv_a, "\", \""));
assert_se(joined = strv_join(strv_a, "\", \""));
log_info(" \"%s\"", r >= 0 ? joined : errno_to_name(r));
joined = mfree(joined);
r = pid_get_cmdline_strv(pid, PROCESS_CMDLINE_COMM_FALLBACK, &strv_b);
if (r >= 0)
ASSERT_NOT_NULL(joined = strv_join(strv_b, "\", \""));
assert_se(joined = strv_join(strv_b, "\", \""));
log_info(" \"%s\"", r >= 0 ? joined : errno_to_name(r));
}
@ -156,13 +151,13 @@ TEST(pid_get_cmdline) {
_cleanup_closedir_ DIR *d = NULL;
int r;
ASSERT_OK(proc_dir_open(&d));
assert_se(proc_dir_open(&d) >= 0);
for (;;) {
pid_t pid;
r = proc_dir_read(d, &pid);
ASSERT_OK(r);
assert_se(r >= 0);
if (r == 0) /* EOF */
break;
@ -176,8 +171,8 @@ static void test_pid_get_comm_escape_one(const char *input, const char *output)
log_debug("input: <%s> — output: <%s>", input, output);
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, input));
ASSERT_OK(pid_get_comm(0, &n));
assert_se(prctl(PR_SET_NAME, input) >= 0);
assert_se(pid_get_comm(0, &n) >= 0);
log_debug("got: <%s>", n);
@ -187,7 +182,7 @@ static void test_pid_get_comm_escape_one(const char *input, const char *output)
TEST(pid_get_comm_escape) {
_cleanup_free_ char *saved = NULL;
ASSERT_OK(pid_get_comm(0, &saved));
assert_se(pid_get_comm(0, &saved) >= 0);
test_pid_get_comm_escape_one("", "");
test_pid_get_comm_escape_one("foo", "foo");
@ -200,62 +195,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("xxxxxäöüß", "xxxxx\\303\\244\\303\\266\\303\\274\\303\\237");
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, saved));
assert_se(prctl(PR_SET_NAME, saved) >= 0);
}
TEST(pid_is_unwaited) {
pid_t pid;
pid = fork();
ASSERT_OK_ERRNO(pid);
assert_se(pid >= 0);
if (pid == 0) {
_exit(EXIT_SUCCESS);
} else {
int status;
ASSERT_OK_EQ_ERRNO(waitpid(pid, &status, 0), pid);
ASSERT_OK_ZERO(pid_is_unwaited(pid));
assert_se(waitpid(pid, &status, 0) == pid);
assert_se(pid_is_unwaited(pid) == 0);
}
ASSERT_OK_POSITIVE(pid_is_unwaited(getpid_cached()));
ASSERT_FAIL(pid_is_unwaited(-1));
assert_se(pid_is_unwaited(getpid_cached()) > 0);
assert_se(pid_is_unwaited(-1) < 0);
}
TEST(pid_is_alive) {
pid_t pid;
pid = fork();
ASSERT_OK_ERRNO(pid);
assert_se(pid >= 0);
if (pid == 0) {
_exit(EXIT_SUCCESS);
} else {
int status;
ASSERT_OK_EQ_ERRNO(waitpid(pid, &status, 0), pid);
ASSERT_OK_ZERO(pid_is_alive(pid));
assert_se(waitpid(pid, &status, 0) == pid);
assert_se(pid_is_alive(pid) == 0);
}
ASSERT_OK_POSITIVE(pid_is_alive(getpid_cached()));
ASSERT_FAIL(pid_is_alive(-1));
assert_se(pid_is_alive(getpid_cached()) > 0);
assert_se(pid_is_alive(-1) < 0);
}
TEST(personality) {
ASSERT_NOT_NULL(personality_to_string(PER_LINUX));
ASSERT_NULL(personality_to_string(PERSONALITY_INVALID));
assert_se(personality_to_string(PER_LINUX));
assert_se(!personality_to_string(PERSONALITY_INVALID));
ASSERT_STREQ(personality_to_string(PER_LINUX), architecture_to_string(native_architecture()));
ASSERT_EQ(personality_from_string(personality_to_string(PER_LINUX)), (unsigned long) PER_LINUX);
ASSERT_EQ(personality_from_string(architecture_to_string(native_architecture())), (unsigned long) PER_LINUX);
assert_se(personality_from_string(personality_to_string(PER_LINUX)) == PER_LINUX);
assert_se(personality_from_string(architecture_to_string(native_architecture())) == PER_LINUX);
#ifdef __x86_64__
ASSERT_STREQ(personality_to_string(PER_LINUX), "x86-64");
ASSERT_STREQ(personality_to_string(PER_LINUX32), "x86");
ASSERT_EQ(personality_from_string("x86-64"), (unsigned long) PER_LINUX);
ASSERT_EQ(personality_from_string("x86"), (unsigned long) PER_LINUX32);
ASSERT_EQ(personality_from_string("ia64"), PERSONALITY_INVALID);
ASSERT_EQ(personality_from_string(NULL), PERSONALITY_INVALID);
assert_se(personality_from_string("x86-64") == PER_LINUX);
assert_se(personality_from_string("x86") == PER_LINUX32);
assert_se(personality_from_string("ia64") == PERSONALITY_INVALID);
assert_se(personality_from_string(NULL) == PERSONALITY_INVALID);
ASSERT_EQ(personality_from_string(personality_to_string(PER_LINUX32)), (unsigned long) PER_LINUX32);
assert_se(personality_from_string(personality_to_string(PER_LINUX32)) == PER_LINUX32);
#endif
}
@ -293,31 +288,30 @@ TEST(pid_get_cmdline_harder) {
(void) wait_for_terminate(pid, &si);
ASSERT_EQ(si.si_code, CLD_EXITED);
ASSERT_OK_ZERO(si.si_status);
assert_se(si.si_code == CLD_EXITED);
assert_se(si.si_status == 0);
return;
}
ASSERT_OK_ZERO(pid);
assert_se(pid == 0);
r = detach_mount_namespace();
if (r < 0) {
log_warning_errno(r, "detach mount namespace failed: %m");
if (!ERRNO_IS_PRIVILEGE(r))
ASSERT_OK(r);
assert_se(ERRNO_IS_PRIVILEGE(r));
return;
}
fd = mkostemp(path, O_CLOEXEC);
ASSERT_OK_ERRNO(fd);
assert_se(fd >= 0);
/* 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. */
if (mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) < 0) {
/* This happens under selinux… Abort the test in this case. */
log_warning_errno(errno, "mount(..., \"/proc/self/cmdline\", \"bind\", ...) failed: %m");
ASSERT_TRUE(IN_SET(errno, EPERM, EACCES));
assert_se(IN_SET(errno, EPERM, EACCES));
return;
}
@ -326,197 +320,197 @@ TEST(pid_get_cmdline_harder) {
if (setrlimit(RLIMIT_STACK, &RLIMIT_MAKE_CONST(RLIM_INFINITY)) < 0)
log_warning("Testing without RLIMIT_STACK=infinity");
ASSERT_OK_ERRNO(unlink(path));
assert_se(unlink(path) >= 0);
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "testa"));
assert_se(prctl(PR_SET_NAME, "testa") >= 0);
ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT);
assert_se(pid_get_cmdline(0, SIZE_MAX, 0, &line) == -ENOENT);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "[testa]");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_QUOTE, &line));
assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_QUOTE, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "\"[testa]\""); /* quoting is enabled here */
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 0, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 0, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
ASSERT_STREQ(line, "");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
ASSERT_STREQ(line, "[…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
ASSERT_STREQ(line, "[t…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
ASSERT_STREQ(line, "[te…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
ASSERT_STREQ(line, "[tes…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
ASSERT_STREQ(line, "[test…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
ASSERT_STREQ(line, "[testa]");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
ASSERT_STREQ(line, "[testa]");
line = mfree(line);
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
ASSERT_TRUE(strv_equal(args, STRV_MAKE("[testa]")));
assert_se(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args) >= 0);
assert_se(strv_equal(args, STRV_MAKE("[testa]")));
args = strv_free(args);
/* Test with multiple arguments that don't require quoting */
ASSERT_OK_EQ_ERRNO(write(fd, "foo\0bar", 8), 8);
assert_se(write(fd, "foo\0bar", 8) == 8);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, 0, &line));
assert_se(pid_get_cmdline(0, SIZE_MAX, 0, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
ASSERT_STREQ(line, "foo bar");
line = mfree(line);
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
ASSERT_TRUE(strv_equal(args, STRV_MAKE("foo", "bar")));
assert_se(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args) >= 0);
assert_se(strv_equal(args, STRV_MAKE("foo", "bar")));
args = strv_free(args);
ASSERT_OK_EQ_ERRNO(write(fd, "quux", 4), 4);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, 0, &line));
assert_se(write(fd, "quux", 4) == 4);
assert_se(pid_get_cmdline(0, SIZE_MAX, 0, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "f…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "fo…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo …");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo b…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo ba…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 9, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 9, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar …");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar q…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar qu…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 13, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 13, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 14, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 14, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 1000, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 1000, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
ASSERT_TRUE(strv_equal(args, STRV_MAKE("foo", "bar", "quux")));
assert_se(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args) >= 0);
assert_se(strv_equal(args, STRV_MAKE("foo", "bar", "quux")));
args = strv_free(args);
ASSERT_OK_ERRNO(ftruncate(fd, 0));
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "aaaa bbbb cccc"));
assert_se(ftruncate(fd, 0) >= 0);
assert_se(prctl(PR_SET_NAME, "aaaa bbbb cccc") >= 0);
ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT);
assert_se(pid_get_cmdline(0, SIZE_MAX, 0, &line) == -ENOENT);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "[aaaa bbbb cccc]");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "[aaaa bbb…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "[aaaa bbbb…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line));
assert_se(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
log_debug("'%s'", line);
ASSERT_STREQ(line, "[aaaa bbbb …");
line = mfree(line);
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
ASSERT_TRUE(strv_equal(args, STRV_MAKE("[aaaa bbbb cccc]")));
assert_se(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args) >= 0);
assert_se(strv_equal(args, STRV_MAKE("[aaaa bbbb cccc]")));
args = strv_free(args);
/* Test with multiple arguments that do require quoting */
@ -526,24 +520,24 @@ TEST(pid_get_cmdline_harder) {
#define EXPECT1p "foo $'\\'bar\\'' $'\"bar$\"' $'x y z' $'!``'"
#define EXPECT1v STRV_MAKE("foo", "'bar'", "\"bar$\"", "x y z", "!``")
ASSERT_OK_ZERO_ERRNO(lseek(fd, SEEK_SET, 0));
ASSERT_OK_EQ_ERRNO(write(fd, CMDLINE1, sizeof(CMDLINE1)), (ssize_t) sizeof(CMDLINE1));
ASSERT_OK_ZERO_ERRNO(ftruncate(fd, sizeof(CMDLINE1)));
assert_se(lseek(fd, SEEK_SET, 0) == 0);
assert_se(write(fd, CMDLINE1, sizeof CMDLINE1) == sizeof CMDLINE1);
assert_se(ftruncate(fd, sizeof CMDLINE1) == 0);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line));
assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line) >= 0);
log_debug("got: ==%s==", line);
log_debug("exp: ==%s==", EXPECT1);
ASSERT_STREQ(line, EXPECT1);
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line));
assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line) >= 0);
log_debug("got: ==%s==", line);
log_debug("exp: ==%s==", EXPECT1p);
ASSERT_STREQ(line, EXPECT1p);
line = mfree(line);
ASSERT_OK(pid_get_cmdline_strv(0, 0, &args));
ASSERT_TRUE(strv_equal(args, EXPECT1v));
assert_se(pid_get_cmdline_strv(0, 0, &args) >= 0);
assert_se(strv_equal(args, EXPECT1v));
args = strv_free(args);
#define CMDLINE2 "foo\0\1\2\3\0\0"
@ -551,24 +545,24 @@ TEST(pid_get_cmdline_harder) {
#define EXPECT2p "foo $'\\001\\002\\003'"
#define EXPECT2v STRV_MAKE("foo", "\1\2\3")
ASSERT_OK_ZERO_ERRNO(lseek(fd, SEEK_SET, 0));
ASSERT_OK_EQ_ERRNO(write(fd, CMDLINE2, sizeof(CMDLINE2)), (ssize_t) sizeof(CMDLINE2));
ASSERT_OK_ZERO_ERRNO(ftruncate(fd, sizeof CMDLINE2));
assert_se(lseek(fd, SEEK_SET, 0) == 0);
assert_se(write(fd, CMDLINE2, sizeof CMDLINE2) == sizeof CMDLINE2);
assert_se(ftruncate(fd, sizeof CMDLINE2) == 0);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line));
assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line) >= 0);
log_debug("got: ==%s==", line);
log_debug("exp: ==%s==", EXPECT2);
ASSERT_STREQ(line, EXPECT2);
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line));
assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line) >= 0);
log_debug("got: ==%s==", line);
log_debug("exp: ==%s==", EXPECT2p);
ASSERT_STREQ(line, EXPECT2p);
line = mfree(line);
ASSERT_OK(pid_get_cmdline_strv(0, 0, &args));
ASSERT_TRUE(strv_equal(args, EXPECT2v));
assert_se(pid_get_cmdline_strv(0, 0, &args) >= 0);
assert_se(strv_equal(args, EXPECT2v));
args = strv_free(args);
safe_close(fd);
@ -583,11 +577,10 @@ TEST(getpid_cached) {
b = getpid_cached();
c = getpid();
ASSERT_EQ(a, b);
ASSERT_EQ(a, c);
assert_se(a == b && a == c);
child = fork();
ASSERT_OK_ERRNO(child);
assert_se(child >= 0);
if (child == 0) {
/* In child */
@ -595,8 +588,7 @@ TEST(getpid_cached) {
b = getpid_cached();
c = getpid();
ASSERT_EQ(a, b);
ASSERT_EQ(a, c);
assert_se(a == b && a == c);
_exit(EXIT_SUCCESS);
}
@ -604,13 +596,11 @@ TEST(getpid_cached) {
e = getpid_cached();
f = getpid();
ASSERT_EQ(a, d);
ASSERT_EQ(a, e);
ASSERT_EQ(a, f);
assert_se(a == d && a == e && a == f);
ASSERT_OK(wait_for_terminate(child, &si));
ASSERT_EQ(si.si_status, 0);
ASSERT_EQ(si.si_code, CLD_EXITED);
assert_se(wait_for_terminate(child, &si) >= 0);
assert_se(si.si_status == 0);
assert_se(si.si_code == CLD_EXITED);
}
TEST(getpid_measure) {
@ -645,7 +635,7 @@ TEST(safe_fork) {
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);
ASSERT_OK(r);
assert_se(r >= 0);
if (r == 0) {
/* child */
@ -654,42 +644,43 @@ TEST(safe_fork) {
_exit(88);
}
ASSERT_OK(wait_for_terminate(pid, &status));
ASSERT_EQ(status.si_code, CLD_EXITED);
ASSERT_EQ(status.si_status, 88);
assert_se(wait_for_terminate(pid, &status) >= 0);
assert_se(status.si_code == CLD_EXITED);
assert_se(status.si_status == 88);
}
TEST(pid_to_ptr) {
ASSERT_EQ(PTR_TO_PID(NULL), 0);
assert_se(PTR_TO_PID(NULL) == 0);
ASSERT_NULL(PID_TO_PTR(0));
ASSERT_EQ(PTR_TO_PID(PID_TO_PTR(1)), 1);
ASSERT_EQ(PTR_TO_PID(PID_TO_PTR(2)), 2);
ASSERT_EQ(PTR_TO_PID(PID_TO_PTR(-1)), -1);
ASSERT_EQ(PTR_TO_PID(PID_TO_PTR(-2)), -2);
assert_se(PTR_TO_PID(PID_TO_PTR(1)) == 1);
assert_se(PTR_TO_PID(PID_TO_PTR(2)) == 2);
assert_se(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(INT16_MAX)), INT16_MAX);
ASSERT_EQ(PTR_TO_PID(PID_TO_PTR(INT16_MIN)), INT16_MIN);
assert_se(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(INT32_MAX)), INT32_MAX);
ASSERT_EQ(PTR_TO_PID(PID_TO_PTR(INT32_MIN)), INT32_MIN);
assert_se(PTR_TO_PID(PID_TO_PTR(INT32_MAX)) == INT32_MAX);
assert_se(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) {
ASSERT_EQ(ioprio_class_from_string(val), expected);
assert_se(ioprio_class_from_string(val) == expected);
if (expected >= 0) {
_cleanup_free_ char *s = NULL;
unsigned ret;
int combined;
ASSERT_OK_ZERO(ioprio_class_to_string_alloc(expected, &s));
assert_se(ioprio_class_to_string_alloc(expected, &s) == 0);
/* We sometimes get a class number and sometimes a name back */
ASSERT_TRUE(streq(s, val) || safe_atou(val, &ret) == 0);
assert_se(streq(s, val) ||
safe_atou(val, &ret) == 0);
/* Make sure normalization works, i.e. NONE → BE gets normalized */
combined = ioprio_normalize(ioprio_prio_value(expected, 0));
ASSERT_EQ(ioprio_prio_class(combined), normalized);
ASSERT_TRUE(expected != IOPRIO_CLASS_NONE || ioprio_prio_data(combined) == 4);
assert_se(ioprio_prio_class(combined) == normalized);
assert_se(expected != IOPRIO_CLASS_NONE || ioprio_prio_data(combined) == 4);
}
}
@ -710,8 +701,8 @@ TEST(setpriority_closest) {
int r;
r = safe_fork("(test-setprio)",
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG|FORK_REOPEN_LOG, NULL);
ASSERT_OK(r);
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG, NULL);
assert_se(r >= 0);
if (r == 0) {
bool full_test;
@ -722,21 +713,16 @@ TEST(setpriority_closest) {
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
* the full test */
if (!ERRNO_IS_PRIVILEGE(errno))
ASSERT_OK_ERRNO(-1);
assert_se(ERRNO_IS_PRIVILEGE(errno));
full_test = false;
} else {
/* 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. */
if (setresgid(GID_NOBODY, GID_NOBODY, GID_NOBODY) < 0) {
/* If the nobody user does not exist (user namespace) we get EINVAL. */
if (!ERRNO_IS_PRIVILEGE(errno) && errno != EINVAL)
ASSERT_OK_ERRNO(-1);
assert_se(ERRNO_IS_PRIVILEGE(errno));
full_test = false;
} else if (setresuid(UID_NOBODY, UID_NOBODY, UID_NOBODY) < 0) {
/* If the nobody user does not exist (user namespace) we get EINVAL. */
if (!ERRNO_IS_PRIVILEGE(errno) && errno != EINVAL)
ASSERT_OK_ERRNO(-1);
assert_se(ERRNO_IS_PRIVILEGE(errno));
full_test = false;
} else
full_test = true;
@ -744,69 +730,61 @@ TEST(setpriority_closest) {
errno = 0;
p = getpriority(PRIO_PROCESS, 0);
ASSERT_EQ(errno, 0);
assert_se(errno == 0);
/* It should always be possible to set our nice level to the current one */
ASSERT_OK_POSITIVE(setpriority_closest(p));
assert_se(setpriority_closest(p) > 0);
errno = 0;
q = getpriority(PRIO_PROCESS, 0);
ASSERT_EQ(errno, 0);
ASSERT_EQ(p, q);
assert_se(errno == 0 && p == q);
/* It should also be possible to set the nice level to one higher */
if (p < PRIO_MAX-1) {
ASSERT_OK_POSITIVE(setpriority_closest(++p));
assert_se(setpriority_closest(++p) > 0);
errno = 0;
q = getpriority(PRIO_PROCESS, 0);
ASSERT_EQ(errno, 0);
ASSERT_EQ(p, q);
assert_se(errno == 0 && p == q);
}
/* It should also be possible to set the nice level to two higher */
if (p < PRIO_MAX-1) {
ASSERT_OK_POSITIVE(setpriority_closest(++p));
assert_se(setpriority_closest(++p) > 0);
errno = 0;
q = getpriority(PRIO_PROCESS, 0);
ASSERT_EQ(errno, 0);
ASSERT_EQ(p, q);
assert_se(errno == 0 && p == q);
}
if (full_test) {
/* These two should work, given the RLIMIT_NICE we set above */
ASSERT_OK_POSITIVE(setpriority_closest(-10));
assert_se(setpriority_closest(-10) > 0);
errno = 0;
q = getpriority(PRIO_PROCESS, 0);
ASSERT_EQ(errno, 0);
ASSERT_EQ(q, -10);
assert_se(errno == 0 && q == -10);
ASSERT_OK_POSITIVE(setpriority_closest(-9));
assert_se(setpriority_closest(-9) > 0);
errno = 0;
q = getpriority(PRIO_PROCESS, 0);
ASSERT_EQ(errno, 0);
ASSERT_EQ(q, -9);
assert_se(errno == 0 && q == -9);
/* This should succeed but should be clamped to the limit */
ASSERT_OK_ZERO(setpriority_closest(-11));
assert_se(setpriority_closest(-11) == 0);
errno = 0;
q = getpriority(PRIO_PROCESS, 0);
ASSERT_EQ(errno, 0);
ASSERT_EQ(q, -10);
assert_se(errno == 0 && q == -10);
ASSERT_OK_POSITIVE(setpriority_closest(-8));
assert_se(setpriority_closest(-8) > 0);
errno = 0;
q = getpriority(PRIO_PROCESS, 0);
ASSERT_EQ(errno, 0);
ASSERT_EQ(q, -8);
assert_se(errno == 0 && q == -8);
/* This should succeed but should be clamped to the limit */
ASSERT_OK_ZERO(setpriority_closest(-12));
assert_se(setpriority_closest(-12) == 0);
errno = 0;
q = getpriority(PRIO_PROCESS, 0);
ASSERT_EQ(errno, 0);
ASSERT_EQ(q, -10);
assert_se(errno == 0 && q == -10);
}
_exit(EXIT_SUCCESS);
@ -817,10 +795,10 @@ TEST(get_process_ppid) {
uint64_t limit;
int r;
ASSERT_ERROR(get_process_ppid(1, NULL), EADDRNOTAVAIL);
assert_se(get_process_ppid(1, NULL) == -EADDRNOTAVAIL);
/* the process with the PID above the global limit definitely doesn't exist. Verify that */
ASSERT_OK(procfs_get_pid_max(&limit));
assert_se(procfs_get_pid_max(&limit) >= 0);
log_debug("kernel.pid_max = %"PRIu64, limit);
if (limit < INT_MAX) {
@ -839,10 +817,10 @@ TEST(get_process_ppid) {
break;
}
ASSERT_OK(r);
assert_se(r >= 0);
ASSERT_OK(pid_get_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &c1));
ASSERT_OK(pid_get_cmdline(ppid, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &c2));
assert_se(pid_get_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &c1) >= 0);
assert_se(pid_get_cmdline(ppid, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &c2) >= 0);
log_info("Parent of " PID_FMT " (%s) is " PID_FMT " (%s).", pid, c1, ppid, c2);
@ -853,20 +831,19 @@ TEST(get_process_ppid) {
TEST(set_oom_score_adjust) {
int a, b, r;
ASSERT_OK(get_oom_score_adjust(&a));
assert_se(get_oom_score_adjust(&a) >= 0);
r = set_oom_score_adjust(OOM_SCORE_ADJ_MIN);
if (!ERRNO_IS_PRIVILEGE(r))
ASSERT_OK(r);
assert_se(r >= 0 || ERRNO_IS_PRIVILEGE(r));
if (r >= 0) {
ASSERT_OK(get_oom_score_adjust(&b));
ASSERT_EQ(b, OOM_SCORE_ADJ_MIN);
assert_se(get_oom_score_adjust(&b) >= 0);
assert_se(b == OOM_SCORE_ADJ_MIN);
}
ASSERT_OK(set_oom_score_adjust(a));
ASSERT_OK(get_oom_score_adjust(&b));
ASSERT_EQ(b, a);
assert_se(set_oom_score_adjust(a) >= 0);
assert_se(get_oom_score_adjust(&b) >= 0);
assert_se(b == a);
}
static void* dummy_thread(void *p) {
@ -874,10 +851,10 @@ static void* dummy_thread(void *p) {
char x;
/* let main thread know we are ready */
ASSERT_OK_EQ_ERRNO(write(fd, &(const char) { 'x' }, 1), 1);
assert_se(write(fd, &(const char) { 'x' }, 1) == 1);
/* wait for the main thread to tell us to shut down */
ASSERT_OK_EQ_ERRNO(read(fd, &x, 1), 1);
assert_se(read(fd, &x, 1) == 1);
return NULL;
}
@ -885,42 +862,38 @@ TEST(get_process_threads) {
int r;
/* 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_WAIT|FORK_LOG, NULL);
ASSERT_OK(r);
r = safe_fork("(nthreads)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_WAIT|FORK_LOG, NULL);
assert_se(r >= 0);
if (r == 0) {
_cleanup_close_pair_ int pfd[2] = EBADF_PAIR, ppfd[2] = EBADF_PAIR;
pthread_t t, tt;
char x;
ASSERT_OK_ERRNO(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, pfd));
ASSERT_OK_ERRNO(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, ppfd));
assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, pfd) >= 0);
assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, ppfd) >= 0);
ASSERT_OK_EQ(get_process_threads(0), 1);
ASSERT_OK_ZERO_ERRNO(pthread_create(&t, NULL, &dummy_thread, FD_TO_PTR(pfd[0])));
ASSERT_OK_EQ_ERRNO(read(pfd[1], &x, 1), 1);
ASSERT_OK_EQ(get_process_threads(0), 2);
ASSERT_OK_ZERO_ERRNO(pthread_create(&tt, NULL, &dummy_thread, FD_TO_PTR(ppfd[0])));
ASSERT_OK_EQ_ERRNO(read(ppfd[1], &x, 1), 1);
ASSERT_OK_EQ(get_process_threads(0), 3);
assert_se(get_process_threads(0) == 1);
assert_se(pthread_create(&t, NULL, &dummy_thread, FD_TO_PTR(pfd[0])) == 0);
assert_se(read(pfd[1], &x, 1) == 1);
assert_se(get_process_threads(0) == 2);
assert_se(pthread_create(&tt, NULL, &dummy_thread, FD_TO_PTR(ppfd[0])) == 0);
assert_se(read(ppfd[1], &x, 1) == 1);
assert_se(get_process_threads(0) == 3);
ASSERT_OK_EQ_ERRNO(write(pfd[1], &(const char) { 'x' }, 1), 1);
ASSERT_OK_ZERO_ERRNO(pthread_join(t, NULL));
assert_se(write(pfd[1], &(const char) { 'x' }, 1) == 1);
assert_se(pthread_join(t, NULL) == 0);
/* 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
* like to check here */
r = get_process_threads(0);
ASSERT_OK(r);
ASSERT_GE(r, 2);
assert_se(get_process_threads(0) >= 2);
ASSERT_OK_EQ_ERRNO(write(ppfd[1], &(const char) { 'x' }, 1), 1);
ASSERT_OK_ZERO_ERRNO(pthread_join(tt, NULL));
assert_se(write(ppfd[1], &(const char) { 'x' }, 1) == 1);
assert_se(pthread_join(tt, NULL) == 0);
/* similar here */
r = get_process_threads(0);
ASSERT_OK(r);
ASSERT_GE(r, 1);
assert_se(get_process_threads(0) >= 1);
_exit(EXIT_SUCCESS);
}
@ -929,17 +902,17 @@ TEST(get_process_threads) {
TEST(is_reaper_process) {
int r;
r = safe_fork("(regular)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_WAIT, NULL);
ASSERT_OK(r);
r = safe_fork("(regular)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_WAIT, NULL);
assert_se(r >= 0);
if (r == 0) {
/* child */
ASSERT_OK_ZERO(is_reaper_process());
assert_se(is_reaper_process() == 0);
_exit(EXIT_SUCCESS);
}
r = safe_fork("(newpid)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_WAIT, NULL);
ASSERT_OK(r);
r = safe_fork("(newpid)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_WAIT, NULL);
assert_se(r >= 0);
if (r == 0) {
/* child */
@ -950,25 +923,25 @@ TEST(is_reaper_process) {
}
}
r = safe_fork("(newpid1)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_WAIT, NULL);
ASSERT_OK(r);
r = safe_fork("(newpid1)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_WAIT, NULL);
assert_se(r >= 0);
if (r == 0) {
/* grandchild, which is PID1 in a pidns */
ASSERT_OK_EQ(getpid_cached(), 1);
ASSERT_OK_POSITIVE(is_reaper_process());
assert_se(getpid_cached() == 1);
assert_se(is_reaper_process() > 0);
_exit(EXIT_SUCCESS);
}
_exit(EXIT_SUCCESS);
}
r = safe_fork("(subreaper)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_WAIT, NULL);
ASSERT_OK(r);
r = safe_fork("(subreaper)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_WAIT, NULL);
assert_se(r >= 0);
if (r == 0) {
/* child */
ASSERT_OK(make_reaper_process(true));
assert_se(make_reaper_process(true) >= 0);
ASSERT_OK_POSITIVE(is_reaper_process());
assert_se(is_reaper_process() > 0);
_exit(EXIT_SUCCESS);
}
}
@ -976,22 +949,22 @@ TEST(is_reaper_process) {
TEST(pid_get_start_time) {
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
ASSERT_OK(pidref_set_self(&pidref));
assert_se(pidref_set_self(&pidref) >= 0);
usec_t start_time;
ASSERT_OK(pidref_get_start_time(&pidref, &start_time));
assert_se(pidref_get_start_time(&pidref, &start_time) >= 0);
log_info("our starttime: " USEC_FMT, start_time);
_cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
ASSERT_OK(pidref_safe_fork("(stub)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG, &child));
assert_se(pidref_safe_fork("(stub)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS, &child) >= 0);
usec_t start_time2;
ASSERT_OK(pidref_get_start_time(&child, &start_time2));
assert_se(pidref_get_start_time(&child, &start_time2) >= 0);
log_info("child starttime: " USEC_FMT, start_time2);
ASSERT_GE(start_time2, start_time);
assert_se(start_time2 >= start_time);
}
static int intro(void) {

View File

@ -259,7 +259,7 @@ static int run(int argc, char *argv[]) {
if (r <= 0)
return r;
if (arg_graceful && !tpm2_is_fully_supported()) {
if (arg_graceful && tpm2_support() != TPM2_SUPPORT_FULL) {
log_notice("No complete TPM2 support detected, exiting gracefully.");
return EXIT_SUCCESS;
}

View File

@ -288,7 +288,7 @@ static int verb_info(int argc, char *argv[], void *userdata) {
pager_open(arg_pager_flags);
if (FLAGS_SET(arg_json_format_flags, SD_JSON_FORMAT_OFF)) {
static const sd_json_dispatch_field dispatch_table[] = {
static const struct sd_json_dispatch_field dispatch_table[] = {
{ "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 },
{ "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)
return r;
static const sd_json_dispatch_field dispatch_table[] = {
{ "interfaces", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_strv, 0, SD_JSON_MANDATORY },
const struct sd_json_dispatch_field dispatch_table[] = {
{ "interfaces", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_strv, PTR_TO_SIZE(&auto_interfaces), SD_JSON_MANDATORY },
{}
};
r = sd_json_dispatch(reply, dispatch_table, SD_JSON_LOG|SD_JSON_ALLOW_EXTENSIONS, &auto_interfaces);
r = sd_json_dispatch(reply, dispatch_table, SD_JSON_LOG|SD_JSON_ALLOW_EXTENSIONS, NULL);
if (r < 0)
return r;
@ -412,7 +412,7 @@ static int verb_introspect(int argc, char *argv[], void *userdata) {
return r;
if (FLAGS_SET(arg_json_format_flags, SD_JSON_FORMAT_OFF) || list_methods) {
static const sd_json_dispatch_field dispatch_table[] = {
static const struct sd_json_dispatch_field dispatch_table[] = {
{ "description", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, 0, SD_JSON_MANDATORY },
{}
};

View File

@ -4,6 +4,5 @@ integration_tests += [
integration_test_template + {
'name' : fs.name(meson.current_source_dir()),
'storage': 'persistent',
'vm' : true,
},
]

View File

@ -21,9 +21,6 @@ at_exit() {
trap at_exit EXIT
systemctl unmask systemd-networkd.service
systemctl start systemd-networkd.service
export NETWORK_NAME="10-networkctl-test-$RANDOM.network"
export NETDEV_NAME="10-networkctl-test-$RANDOM.netdev"
export LINK_NAME="10-networkctl-test-$RANDOM.link"
@ -78,6 +75,15 @@ cmp "+4" "/etc/systemd/network/${NETWORK_NAME}.d/test.conf"
networkctl cat "$NETWORK_NAME" | grep '^# ' |
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
[Match]
OriginalName=test2
@ -89,23 +95,13 @@ EOF
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"
# The interface test2 does not exist, hence the below do not work.
# Test links
systemctl unmask systemd-networkd
systemctl stop systemd-networkd
(! networkctl cat @test2)
(! networkctl cat @test2:netdev)
(! networkctl cat @test2:link)
(! networkctl cat @test2:network)
# 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.
systemctl start systemd-networkd
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")