summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2022-08-11 10:15:02 +0200
committerThomas Haller <thaller@redhat.com>2022-08-11 21:51:58 +0200
commitad1bf3c5448e440f8f09be601fa37a69976dd79b (patch)
tree2f48ccdf9a0bc1314cd3e213e7877875093936c4
parent082e6c96a1ea369b6666217663327c1d4fa481a4 (diff)
parent7c0de1517ce589e9fa2837eeb705b788d829d055 (diff)
downloadNetworkManager-ad1bf3c5448e440f8f09be601fa37a69976dd79b.tar.gz
systemd: merge branch systemd into main
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1333
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.c55
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.h7
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/dhcp6-internal.h1
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.c14
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c30
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-lease.c34
-rw-r--r--src/libnm-systemd-core/src/libsystemd/sd-event/sd-event.c76
-rw-r--r--src/libnm-systemd-core/src/systemd/_sd-common.h2
-rw-r--r--src/libnm-systemd-core/src/systemd/sd-dhcp6-client.h1
-rw-r--r--src/libnm-systemd-shared/sd-adapt-shared/nm-sd-adapt-shared.h2
-rw-r--r--src/libnm-systemd-shared/src/basic/alloc-util.h18
-rw-r--r--src/libnm-systemd-shared/src/basic/ether-addr-util.c9
-rw-r--r--src/libnm-systemd-shared/src/basic/ether-addr-util.h2
-rw-r--r--src/libnm-systemd-shared/src/basic/fd-util.c2
-rw-r--r--src/libnm-systemd-shared/src/basic/hash-funcs.c4
-rw-r--r--src/libnm-systemd-shared/src/basic/hash-funcs.h1
-rw-r--r--src/libnm-systemd-shared/src/basic/hashmap.h7
-rw-r--r--src/libnm-systemd-shared/src/basic/in-addr-util.c14
-rw-r--r--src/libnm-systemd-shared/src/basic/in-addr-util.h1
-rw-r--r--src/libnm-systemd-shared/src/basic/list.h3
-rw-r--r--src/libnm-systemd-shared/src/basic/macro.h4
-rw-r--r--src/libnm-systemd-shared/src/basic/path-util.c4
-rw-r--r--src/libnm-systemd-shared/src/basic/path-util.h12
-rw-r--r--src/libnm-systemd-shared/src/basic/process-util.c34
-rw-r--r--src/libnm-systemd-shared/src/basic/process-util.h2
-rw-r--r--src/libnm-systemd-shared/src/basic/set.h7
-rw-r--r--src/libnm-systemd-shared/src/basic/stat-util.c20
-rw-r--r--src/libnm-systemd-shared/src/basic/stat-util.h9
-rw-r--r--src/libnm-systemd-shared/src/basic/strv.h9
-rw-r--r--src/libnm-systemd-shared/src/basic/time-util.c2
-rw-r--r--src/libnm-systemd-shared/src/fundamental/macro-fundamental.h56
31 files changed, 282 insertions, 160 deletions
diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.c b/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.c
index 46410ca10f..2636d7967f 100644
--- a/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.c
+++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.c
@@ -66,20 +66,26 @@ int dhcp_validate_duid_len(DUIDType duid_type, size_t duid_len, bool strict) {
}
#if 0 /* NM_IGNORED */
-static int dhcp_identifier_set_duid_llt(const uint8_t *addr, size_t addr_len, uint16_t arp_type, usec_t t, struct duid *ret_duid, size_t *ret_len) {
+static int dhcp_identifier_set_duid_llt(
+ const struct hw_addr_data *hw_addr,
+ uint16_t arp_type,
+ usec_t t,
+ struct duid *ret_duid,
+ size_t *ret_len) {
+
uint16_t time_from_2000y;
- assert(addr);
+ assert(hw_addr);
assert(ret_duid);
assert(ret_len);
- if (addr_len == 0)
+ if (hw_addr->length == 0)
return -EOPNOTSUPP;
if (arp_type == ARPHRD_ETHER)
- assert_return(addr_len == ETH_ALEN, -EINVAL);
+ assert_return(hw_addr->length == ETH_ALEN, -EINVAL);
else if (arp_type == ARPHRD_INFINIBAND)
- assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
+ assert_return(hw_addr->length == INFINIBAND_ALEN, -EINVAL);
else
return -EOPNOTSUPP;
@@ -91,33 +97,38 @@ static int dhcp_identifier_set_duid_llt(const uint8_t *addr, size_t addr_len, ui
unaligned_write_be16(&ret_duid->type, DUID_TYPE_LLT);
unaligned_write_be16(&ret_duid->llt.htype, arp_type);
unaligned_write_be32(&ret_duid->llt.time, time_from_2000y);
- memcpy(ret_duid->llt.haddr, addr, addr_len);
+ memcpy(ret_duid->llt.haddr, hw_addr->bytes, hw_addr->length);
- *ret_len = offsetof(struct duid, llt.haddr) + addr_len;
+ *ret_len = offsetof(struct duid, llt.haddr) + hw_addr->length;
return 0;
}
-static int dhcp_identifier_set_duid_ll(const uint8_t *addr, size_t addr_len, uint16_t arp_type, struct duid *ret_duid, size_t *ret_len) {
- assert(addr);
+static int dhcp_identifier_set_duid_ll(
+ const struct hw_addr_data *hw_addr,
+ uint16_t arp_type,
+ struct duid *ret_duid,
+ size_t *ret_len) {
+
+ assert(hw_addr);
assert(ret_duid);
assert(ret_len);
- if (addr_len == 0)
+ if (hw_addr->length == 0)
return -EOPNOTSUPP;
if (arp_type == ARPHRD_ETHER)
- assert_return(addr_len == ETH_ALEN, -EINVAL);
+ assert_return(hw_addr->length == ETH_ALEN, -EINVAL);
else if (arp_type == ARPHRD_INFINIBAND)
- assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
+ assert_return(hw_addr->length == INFINIBAND_ALEN, -EINVAL);
else
return -EOPNOTSUPP;
unaligned_write_be16(&ret_duid->type, DUID_TYPE_LL);
unaligned_write_be16(&ret_duid->ll.htype, arp_type);
- memcpy(ret_duid->ll.haddr, addr, addr_len);
+ memcpy(ret_duid->ll.haddr, hw_addr->bytes, hw_addr->length);
- *ret_len = offsetof(struct duid, ll.haddr) + addr_len;
+ *ret_len = offsetof(struct duid, ll.haddr) + hw_addr->length;
return 0;
}
@@ -179,8 +190,7 @@ static int dhcp_identifier_set_duid_uuid(struct duid *ret_duid, size_t *ret_len)
int dhcp_identifier_set_duid(
DUIDType duid_type,
- const uint8_t *addr,
- size_t addr_len,
+ const struct hw_addr_data *hw_addr,
uint16_t arp_type,
usec_t llt_time,
bool test_mode,
@@ -189,11 +199,11 @@ int dhcp_identifier_set_duid(
switch (duid_type) {
case DUID_TYPE_LLT:
- return dhcp_identifier_set_duid_llt(addr, addr_len, arp_type, llt_time, ret_duid, ret_len);
+ return dhcp_identifier_set_duid_llt(hw_addr, arp_type, llt_time, ret_duid, ret_len);
case DUID_TYPE_EN:
return dhcp_identifier_set_duid_en(test_mode, ret_duid, ret_len);
case DUID_TYPE_LL:
- return dhcp_identifier_set_duid_ll(addr, addr_len, arp_type, ret_duid, ret_len);
+ return dhcp_identifier_set_duid_ll(hw_addr, arp_type, ret_duid, ret_len);
case DUID_TYPE_UUID:
return dhcp_identifier_set_duid_uuid(ret_duid, ret_len);
default:
@@ -204,8 +214,7 @@ int dhcp_identifier_set_duid(
int dhcp_identifier_set_iaid(
int ifindex,
- const uint8_t *mac,
- size_t mac_len,
+ const struct hw_addr_data *hw_addr,
bool legacy_unstable_byteorder,
bool use_mac,
void *ret) {
@@ -219,6 +228,10 @@ int dhcp_identifier_set_iaid(
uint64_t id;
int r;
+ assert(ifindex > 0);
+ assert(hw_addr);
+ assert(ret);
+
if (udev_available() && !use_mac) {
/* udev should be around */
@@ -247,7 +260,7 @@ int dhcp_identifier_set_iaid(
id = siphash24(name, strlen(name), HASH_KEY.bytes);
else
/* fall back to MAC address if no predictable name available */
- id = siphash24(mac, mac_len, HASH_KEY.bytes);
+ id = siphash24(hw_addr->bytes, hw_addr->length, HASH_KEY.bytes);
id32 = (id & 0xffffffff) ^ (id >> 32);
diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.h b/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.h
index 697ba3bfbb..8acb8c3210 100644
--- a/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.h
+++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.h
@@ -3,6 +3,7 @@
#include "sd-id128.h"
+#include "ether-addr-util.h"
#include "macro.h"
#include "sparse-endian.h"
#include "time-util.h"
@@ -58,8 +59,7 @@ int dhcp_validate_duid_len(DUIDType duid_type, size_t duid_len, bool strict);
int dhcp_identifier_set_duid_en(bool test_mode, struct duid *ret_duid, size_t *ret_len);
int dhcp_identifier_set_duid(
DUIDType duid_type,
- const uint8_t *addr,
- size_t addr_len,
+ const struct hw_addr_data *hw_addr,
uint16_t arp_type,
usec_t llt_time,
bool test_mode,
@@ -67,8 +67,7 @@ int dhcp_identifier_set_duid(
size_t *ret_len);
int dhcp_identifier_set_iaid(
int ifindex,
- const uint8_t *mac,
- size_t mac_len,
+ const struct hw_addr_data *hw_addr,
bool legacy_unstable_byteorder,
bool use_mac,
void *ret);
diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-internal.h b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-internal.h
index 176391ebec..65f6cb057f 100644
--- a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-internal.h
+++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-internal.h
@@ -71,6 +71,7 @@ struct sd_dhcp6_client {
char **vendor_class;
OrderedHashmap *extra_options;
OrderedSet *vendor_options;
+ bool rapid_commit;
struct sd_dhcp6_lease *lease;
diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.c b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.c
index e6b7f7d991..05f2a3838d 100644
--- a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.c
+++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.c
@@ -510,7 +510,7 @@ int dhcp6_option_parse(
if (buflen < offsetof(DHCP6Option, data))
return -EBADMSG;
- if (*offset >= buflen - offsetof(DHCP6Option, data))
+ if (*offset > buflen - offsetof(DHCP6Option, data))
return -EBADMSG;
len = unaligned_read_be16(buf + *offset + offsetof(DHCP6Option, len));
@@ -520,14 +520,14 @@ int dhcp6_option_parse(
*ret_option_code = unaligned_read_be16(buf + *offset + offsetof(DHCP6Option, code));
*ret_option_data_len = len;
- *ret_option_data = buf + *offset + offsetof(DHCP6Option, data);
+ *ret_option_data = len == 0 ? NULL : buf + *offset + offsetof(DHCP6Option, data);
*offset += offsetof(DHCP6Option, data) + len;
return 0;
}
int dhcp6_option_parse_status(const uint8_t *data, size_t data_len, char **ret_status_message) {
- assert(data);
+ assert(data || data_len == 0);
if (data_len < sizeof(uint16_t))
return -EBADMSG;
@@ -805,7 +805,7 @@ int dhcp6_option_parse_addresses(
struct in6_addr **addrs,
size_t *count) {
- assert(optval);
+ assert(optval || optlen == 0);
assert(addrs);
assert(count);
@@ -828,8 +828,8 @@ static int parse_domain(const uint8_t **data, size_t *len, char **ret) {
int r;
assert(data);
- assert(*data);
assert(len);
+ assert(*data || *len == 0);
assert(ret);
optval = *data;
@@ -893,7 +893,7 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, size_t optlen, char **r
_cleanup_free_ char *domain = NULL;
int r;
- assert(optval);
+ assert(optval || optlen == 0);
assert(ret);
r = parse_domain(&optval, &optlen, &domain);
@@ -912,7 +912,7 @@ int dhcp6_option_parse_domainname_list(const uint8_t *optval, size_t optlen, cha
_cleanup_strv_free_ char **names = NULL;
int r;
- assert(optval);
+ assert(optval || optlen == 0);
assert(ret);
if (optlen <= 1)
diff --git a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c
index 27efabab4e..fbe15f003b 100644
--- a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c
@@ -122,9 +122,8 @@ int sd_dhcp6_client_set_mac(
return 0;
}
- memcpy(client->hw_addr.bytes, addr, addr_len);
- client->hw_addr.length = addr_len;
client->arp_type = arp_type;
+ hw_addr_set(&client->hw_addr, addr, addr_len);
return 0;
}
@@ -223,8 +222,8 @@ static int dhcp6_client_set_duid_internal(
} else {
#if 0 /* NM_IGNORED */
- r = dhcp_identifier_set_duid(duid_type, client->hw_addr.bytes, client->hw_addr.length,
- client->arp_type, llt_time, client->test_mode, &client->duid, &client->duid_len);
+ r = dhcp_identifier_set_duid(duid_type, &client->hw_addr, client->arp_type, llt_time,
+ client->test_mode, &client->duid, &client->duid_len);
if (r == -EOPNOTSUPP)
return log_dhcp6_client_errno(client, r,
"Failed to set %s. MAC address is not set or "
@@ -310,7 +309,7 @@ static int client_ensure_iaid(sd_dhcp6_client *client) {
if (client->iaid_set)
return 0;
- r = dhcp_identifier_set_iaid(client->ifindex, client->hw_addr.bytes, client->hw_addr.length,
+ r = dhcp_identifier_set_iaid(client->ifindex, &client->hw_addr,
/* legacy_unstable_byteorder = */ true,
/* use_mac = */ client->test_mode,
&iaid);
@@ -501,6 +500,14 @@ int dhcp6_client_set_transaction_id(sd_dhcp6_client *client, uint32_t transactio
return 0;
}
+int sd_dhcp6_client_set_rapid_commit(sd_dhcp6_client *client, int enable) {
+ assert_return(client, -EINVAL);
+ assert_return(!sd_dhcp6_client_is_running(client), -EBUSY);
+
+ client->rapid_commit = enable;
+ return 0;
+}
+
int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) {
assert_return(client, -EINVAL);
@@ -724,9 +731,11 @@ int dhcp6_client_send_message(sd_dhcp6_client *client) {
break;
case DHCP6_STATE_SOLICITATION:
- r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
- if (r < 0)
- return r;
+ if (client->rapid_commit) {
+ r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
+ if (r < 0)
+ return r;
+ }
r = client_append_common_options_in_managed_mode(client, &opt, &optlen,
&client->ia_na, &client->ia_pd);
@@ -1170,6 +1179,10 @@ static int client_process_advertise_or_rapid_commit_reply(
if (message->type == DHCP6_MESSAGE_REPLY) {
bool rapid_commit;
+ if (!client->rapid_commit)
+ return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
+ "Received unexpected reply message, even we sent a solicit message without the rapid commit option, ignoring.");
+
r = dhcp6_lease_get_rapid_commit(lease, &rapid_commit);
if (r < 0)
return r;
@@ -1477,6 +1490,7 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
.ifindex = -1,
.request_ia = DHCP6_REQUEST_IA_NA | DHCP6_REQUEST_IA_PD,
.fd = -1,
+ .rapid_commit = true,
};
*ret = TAKE_PTR(client);
diff --git a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-lease.c b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-lease.c
index 00927d72e2..55c7d627e4 100644
--- a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-lease.c
@@ -469,7 +469,9 @@ static int dhcp6_lease_parse_message(
r = dhcp6_option_parse(message->options, len, &offset, &optcode, &optlen, &optval);
if (r < 0)
- return r;
+ return log_dhcp6_client_errno(client, r,
+ "Failed to parse option header at offset %zu of total length %zu: %m",
+ offset, len);
switch (optcode) {
case SD_DHCP6_OPTION_CLIENTID:
@@ -479,7 +481,7 @@ static int dhcp6_lease_parse_message(
r = dhcp6_lease_set_clientid(lease, optval, optlen);
if (r < 0)
- return r;
+ return log_dhcp6_client_errno(client, r, "Failed to set client ID: %m");
break;
@@ -490,17 +492,17 @@ static int dhcp6_lease_parse_message(
r = dhcp6_lease_set_serverid(lease, optval, optlen);
if (r < 0)
- return r;
+ return log_dhcp6_client_errno(client, r, "Failed to set server ID: %m");
break;
case SD_DHCP6_OPTION_PREFERENCE:
if (optlen != 1)
- return -EINVAL;
+ return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "Received invalid length for preference.");
r = dhcp6_lease_set_preference(lease, optval[0]);
if (r < 0)
- return r;
+ return log_dhcp6_client_errno(client, r, "Failed to set preference: %m");
break;
@@ -509,7 +511,7 @@ static int dhcp6_lease_parse_message(
r = dhcp6_option_parse_status(optval, optlen, &msg);
if (r < 0)
- return r;
+ return log_dhcp6_client_errno(client, r, "Failed to parse status code: %m");
if (r > 0)
return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
@@ -529,9 +531,11 @@ static int dhcp6_lease_parse_message(
r = dhcp6_option_parse_ia(client, client->ia_na.header.id, optcode, optlen, optval, &ia);
if (r == -ENOMEM)
- return r;
- if (r < 0)
+ return log_oom_debug();
+ if (r < 0) {
+ log_dhcp6_client_errno(client, r, "Failed to parse IA_NA option, ignoring: %m");
continue;
+ }
if (lease->ia_na) {
log_dhcp6_client(client, "Received duplicate matching IA_NA option, ignoring.");
@@ -552,9 +556,11 @@ static int dhcp6_lease_parse_message(
r = dhcp6_option_parse_ia(client, client->ia_pd.header.id, optcode, optlen, optval, &ia);
if (r == -ENOMEM)
- return r;
- if (r < 0)
+ return log_oom_debug();
+ if (r < 0) {
+ log_dhcp6_client_errno(client, r, "Failed to parse IA_PD option, ignoring: %m");
continue;
+ }
if (lease->ia_pd) {
log_dhcp6_client(client, "Received duplicate matching IA_PD option, ignoring.");
@@ -566,9 +572,12 @@ static int dhcp6_lease_parse_message(
break;
}
case SD_DHCP6_OPTION_RAPID_COMMIT:
+ if (optlen != 0)
+ log_dhcp6_client(client, "Received rapid commit option with an invalid length (%zu), ignoring.", optlen);
+
r = dhcp6_lease_set_rapid_commit(lease);
if (r < 0)
- return r;
+ return log_dhcp6_client_errno(client, r, "Failed to set rapid commit flag: %m");
break;
@@ -609,7 +618,8 @@ static int dhcp6_lease_parse_message(
case SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME:
if (optlen != 4)
- return -EINVAL;
+ return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
+ "Received information refresh time option with an invalid length (%zu).", optlen);
irt = unaligned_read_be32((be32_t *) optval) * USEC_PER_SEC;
break;
diff --git a/src/libnm-systemd-core/src/libsystemd/sd-event/sd-event.c b/src/libnm-systemd-core/src/libsystemd/sd-event/sd-event.c
index 54081d1897..8b2c554cfa 100644
--- a/src/libnm-systemd-core/src/libsystemd/sd-event/sd-event.c
+++ b/src/libnm-systemd-core/src/libsystemd/sd-event/sd-event.c
@@ -51,19 +51,19 @@ static bool event_source_is_offline(sd_event_source *s) {
}
static const char* const event_source_type_table[_SOURCE_EVENT_SOURCE_TYPE_MAX] = {
- [SOURCE_IO] = "io",
- [SOURCE_TIME_REALTIME] = "realtime",
- [SOURCE_TIME_BOOTTIME] = "bootime",
- [SOURCE_TIME_MONOTONIC] = "monotonic",
+ [SOURCE_IO] = "io",
+ [SOURCE_TIME_REALTIME] = "realtime",
+ [SOURCE_TIME_BOOTTIME] = "bootime",
+ [SOURCE_TIME_MONOTONIC] = "monotonic",
[SOURCE_TIME_REALTIME_ALARM] = "realtime-alarm",
[SOURCE_TIME_BOOTTIME_ALARM] = "boottime-alarm",
- [SOURCE_SIGNAL] = "signal",
- [SOURCE_CHILD] = "child",
- [SOURCE_DEFER] = "defer",
- [SOURCE_POST] = "post",
- [SOURCE_EXIT] = "exit",
- [SOURCE_WATCHDOG] = "watchdog",
- [SOURCE_INOTIFY] = "inotify",
+ [SOURCE_SIGNAL] = "signal",
+ [SOURCE_CHILD] = "child",
+ [SOURCE_DEFER] = "defer",
+ [SOURCE_POST] = "post",
+ [SOURCE_EXIT] = "exit",
+ [SOURCE_WATCHDOG] = "watchdog",
+ [SOURCE_INOTIFY] = "inotify",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(event_source_type, int);
@@ -126,10 +126,10 @@ struct sd_event {
Hashmap *inotify_data; /* indexed by priority */
/* A list of inode structures that still have an fd open, that we need to close before the next loop iteration */
- LIST_HEAD(struct inode_data, inode_data_to_close);
+ LIST_HEAD(struct inode_data, inode_data_to_close_list);
/* A list of inotify objects that already have events buffered which aren't processed yet */
- LIST_HEAD(struct inotify_data, inotify_data_buffered);
+ LIST_HEAD(struct inotify_data, buffered_inotify_data_list);
pid_t original_pid;
@@ -422,6 +422,8 @@ fail:
}
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_event, sd_event, event_free);
+#define PROTECT_EVENT(e) \
+ _unused_ _cleanup_(sd_event_unrefp) sd_event *_ref = sd_event_ref(e);
_public_ sd_event_source* sd_event_source_disable_unref(sd_event_source *s) {
if (s)
@@ -1696,7 +1698,7 @@ static void event_free_inotify_data(sd_event *e, struct inotify_data *d) {
assert(hashmap_isempty(d->wd));
if (d->buffer_filled > 0)
- LIST_REMOVE(buffered, e->inotify_data_buffered, d);
+ LIST_REMOVE(buffered, e->buffered_inotify_data_list, d);
hashmap_free(d->inodes);
hashmap_free(d->wd);
@@ -1805,10 +1807,10 @@ static void event_free_inode_data(
if (!d)
return;
- assert(LIST_IS_EMPTY(d->event_sources));
+ assert(!d->event_sources);
if (d->fd >= 0) {
- LIST_REMOVE(to_close, e->inode_data_to_close, d);
+ LIST_REMOVE(to_close, e->inode_data_to_close_list, d);
safe_close(d->fd);
}
@@ -1868,7 +1870,7 @@ static void event_gc_inode_data(
if (!d)
return;
- if (!LIST_IS_EMPTY(d->event_sources))
+ if (d->event_sources)
return;
inotify_data = d->inotify_data;
@@ -2070,7 +2072,7 @@ static int event_add_inotify_fd_internal(
}
}
- LIST_PREPEND(to_close, e->inode_data_to_close, inode_data);
+ LIST_PREPEND(to_close, e->inode_data_to_close_list, inode_data);
}
/* Link our event source to the inode data object */
@@ -2143,12 +2145,9 @@ static sd_event_source* event_source_free(sd_event_source *s) {
* we still retain a valid event source object after
* the callback. */
- if (s->dispatching) {
- if (s->type == SOURCE_IO)
- source_io_unregister(s);
-
+ if (s->dispatching)
source_disconnect(s);
- } else
+ else
source_free(s);
return NULL;
@@ -2357,7 +2356,7 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority)
goto fail;
}
- LIST_PREPEND(to_close, s->event->inode_data_to_close, new_inode_data);
+ LIST_PREPEND(to_close, s->event->inode_data_to_close_list, new_inode_data);
}
/* Move the event source to the new inode data structure */
@@ -3423,7 +3422,7 @@ static int event_inotify_data_read(sd_event *e, struct inotify_data *d, uint32_t
assert(n > 0);
d->buffer_filled = (size_t) n;
- LIST_PREPEND(buffered, e->inotify_data_buffered, d);
+ LIST_PREPEND(buffered, e->buffered_inotify_data_list, d);
return 1;
}
@@ -3441,7 +3440,7 @@ static void event_inotify_data_drop(sd_event *e, struct inotify_data *d, size_t
d->buffer_filled -= sz;
if (d->buffer_filled == 0)
- LIST_REMOVE(buffered, e->inotify_data_buffered, d);
+ LIST_REMOVE(buffered, e->buffered_inotify_data_list, d);
}
static int event_inotify_data_process(sd_event *e, struct inotify_data *d) {
@@ -3534,7 +3533,7 @@ static int process_inotify(sd_event *e) {
assert(e);
- LIST_FOREACH(buffered, d, e->inotify_data_buffered) {
+ LIST_FOREACH(buffered, d, e->buffered_inotify_data_list) {
r = event_inotify_data_process(e, d);
if (r < 0)
return r;
@@ -3546,8 +3545,8 @@ static int process_inotify(sd_event *e) {
}
static int source_dispatch(sd_event_source *s) {
- _cleanup_(sd_event_unrefp) sd_event *saved_event = NULL;
EventSourceType saved_type;
+ sd_event *saved_event;
int r = 0;
assert(s);
@@ -3559,7 +3558,8 @@ static int source_dispatch(sd_event_source *s) {
/* Similarly, store a reference to the event loop object, so that we can still access it after the
* callback might have invalidated/disconnected the event source. */
- saved_event = sd_event_ref(s->event);
+ saved_event = s->event;
+ PROTECT_EVENT(saved_event);
/* Check if we hit the ratelimit for this event source, and if so, let's disable it. */
assert(!s->ratelimited);
@@ -3760,7 +3760,7 @@ static int dispatch_exit(sd_event *e) {
return 0;
}
- _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
+ PROTECT_EVENT(e);
e->iteration++;
e->state = SD_EVENT_EXITING;
r = source_dispatch(p);
@@ -3831,11 +3831,11 @@ static void event_close_inode_data_fds(sd_event *e) {
* for the inode). Hence, let's close them when entering the first iteration after they were added, as a
* compromise. */
- while ((d = e->inode_data_to_close)) {
+ while ((d = e->inode_data_to_close_list)) {
assert(d->fd >= 0);
d->fd = safe_close(d->fd);
- LIST_REMOVE(to_close, e->inode_data_to_close, d);
+ LIST_REMOVE(to_close, e->inode_data_to_close_list, d);
}
}
@@ -3854,7 +3854,7 @@ _public_ int sd_event_prepare(sd_event *e) {
assert_return(!e->default_event_ptr || e->tid == gettid(), -EREMOTEIO);
/* Make sure that none of the preparation callbacks ends up freeing the event source under our feet */
- _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
+ PROTECT_EVENT(e);
if (e->exit_requested)
goto pending;
@@ -3889,7 +3889,7 @@ _public_ int sd_event_prepare(sd_event *e) {
event_close_inode_data_fds(e);
- if (event_next_pending(e) || e->need_process_child || !LIST_IS_EMPTY(e->inotify_data_buffered))
+ if (event_next_pending(e) || e->need_process_child || e->buffered_inotify_data_list)
goto pending;
e->state = SD_EVENT_ARMED;
@@ -3969,7 +3969,7 @@ static int process_epoll(sd_event *e, usec_t timeout, int64_t threshold, int64_t
n_event_max = MALLOC_ELEMENTSOF(e->event_queue);
/* If we still have inotify data buffered, then query the other fds, but don't wait on it */
- if (!LIST_IS_EMPTY(e->inotify_data_buffered))
+ if (e->buffered_inotify_data_list)
timeout = 0;
for (;;) {
@@ -4184,7 +4184,7 @@ _public_ int sd_event_dispatch(sd_event *e) {
p = event_next_pending(e);
if (p) {
- _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
+ PROTECT_EVENT(e);
e->state = SD_EVENT_RUNNING;
r = source_dispatch(p);
@@ -4236,7 +4236,7 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) {
}
/* Make sure that none of the preparation callbacks ends up freeing the event source under our feet */
- _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
+ PROTECT_EVENT(e);
r = sd_event_prepare(e);
if (r == 0)
@@ -4266,7 +4266,7 @@ _public_ int sd_event_loop(sd_event *e) {
assert_return(!event_pid_changed(e), -ECHILD);
assert_return(e->state == SD_EVENT_INITIAL, -EBUSY);
- _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
+ PROTECT_EVENT(e);
while (e->state != SD_EVENT_FINISHED) {
r = sd_event_run(e, UINT64_MAX);
diff --git a/src/libnm-systemd-core/src/systemd/_sd-common.h b/src/libnm-systemd-core/src/systemd/_sd-common.h
index 38449463e2..6f657c2254 100644
--- a/src/libnm-systemd-core/src/systemd/_sd-common.h
+++ b/src/libnm-systemd-core/src/systemd/_sd-common.h
@@ -85,7 +85,7 @@ typedef void (*_sd_destroy_t)(void *userdata);
#endif
#ifndef _SD_ARRAY_STATIC
-# if __STDC_VERSION__ >= 199901L
+# if __STDC_VERSION__ >= 199901L && !defined(__cplusplus)
# define _SD_ARRAY_STATIC static
# else
# define _SD_ARRAY_STATIC
diff --git a/src/libnm-systemd-core/src/systemd/sd-dhcp6-client.h b/src/libnm-systemd-core/src/systemd/sd-dhcp6-client.h
index 7fe60c356c..2c66c51b78 100644
--- a/src/libnm-systemd-core/src/systemd/sd-dhcp6-client.h
+++ b/src/libnm-systemd-core/src/systemd/sd-dhcp6-client.h
@@ -262,6 +262,7 @@ int sd_dhcp6_client_set_address_request(sd_dhcp6_client *client,
int request);
int sd_dhcp6_client_add_vendor_option(sd_dhcp6_client *client,
sd_dhcp6_option *v);
+int sd_dhcp6_client_set_rapid_commit(sd_dhcp6_client *client, int enable);
int sd_dhcp6_client_get_lease(
sd_dhcp6_client *client,
diff --git a/src/libnm-systemd-shared/sd-adapt-shared/nm-sd-adapt-shared.h b/src/libnm-systemd-shared/sd-adapt-shared/nm-sd-adapt-shared.h
index a3e490f569..ee5a0a240d 100644
--- a/src/libnm-systemd-shared/sd-adapt-shared/nm-sd-adapt-shared.h
+++ b/src/libnm-systemd-shared/sd-adapt-shared/nm-sd-adapt-shared.h
@@ -51,6 +51,8 @@
#define LOG_TRACE 0
+#define WANT_LINUX_FS_H 0
+
#define BUILD_MODE_DEVELOPER (NM_MORE_ASSERTS > 0)
#define LOG_MESSAGE_VERIFICATION (NM_MORE_ASSERTS > 0)
diff --git a/src/libnm-systemd-shared/src/basic/alloc-util.h b/src/libnm-systemd-shared/src/basic/alloc-util.h
index 13dab0304f..b38db7d473 100644
--- a/src/libnm-systemd-shared/src/basic/alloc-util.h
+++ b/src/libnm-systemd-shared/src/basic/alloc-util.h
@@ -50,16 +50,30 @@ typedef void* (*mfree_func_t)(void *p);
#define malloc0(n) (calloc(1, (n) ?: 1))
-#define free_and_replace(a, b) \
+#define free_and_replace_full(a, b, free_func) \
({ \
typeof(a)* _a = &(a); \
typeof(b)* _b = &(b); \
- free(*_a); \
+ free_func(*_a); \
*_a = *_b; \
*_b = NULL; \
0; \
})
+#define free_and_replace(a, b) \
+ free_and_replace_full(a, b, free)
+
+/* This is similar to free_and_replace_full(), but NULL is not assigned to 'b', and its reference counter is
+ * increased. */
+#define unref_and_replace_full(a, b, ref_func, unref_func) \
+ ({ \
+ typeof(a)* _a = &(a); \
+ typeof(b) _b = ref_func(b); \
+ unref_func(*_a); \
+ *_a = _b; \
+ 0; \
+ })
+
void* memdup(const void *p, size_t l) _alloc_(2);
void* memdup_suffix0(const void *p, size_t l); /* We can't use _alloc_() here, since we return a buffer one byte larger than the specified size */
diff --git a/src/libnm-systemd-shared/src/basic/ether-addr-util.c b/src/libnm-systemd-shared/src/basic/ether-addr-util.c
index 4504b6be1f..7984ddf4ad 100644
--- a/src/libnm-systemd-shared/src/basic/ether-addr-util.c
+++ b/src/libnm-systemd-shared/src/basic/ether-addr-util.c
@@ -35,6 +35,15 @@ char *hw_addr_to_string_full(
return buffer;
}
+struct hw_addr_data *hw_addr_set(struct hw_addr_data *addr, const uint8_t *bytes, size_t length) {
+ assert(addr);
+ assert(length <= HW_ADDR_MAX_SIZE);
+
+ addr->length = length;
+ memcpy_safe(addr->bytes, bytes, length);
+ return addr;
+}
+
int hw_addr_compare(const struct hw_addr_data *a, const struct hw_addr_data *b) {
int r;
diff --git a/src/libnm-systemd-shared/src/basic/ether-addr-util.h b/src/libnm-systemd-shared/src/basic/ether-addr-util.h
index 32f45fe813..83ed77d634 100644
--- a/src/libnm-systemd-shared/src/basic/ether-addr-util.h
+++ b/src/libnm-systemd-shared/src/basic/ether-addr-util.h
@@ -52,6 +52,8 @@ static inline char *hw_addr_to_string(const struct hw_addr_data *addr, char buff
#define HW_ADDR_NULL ((const struct hw_addr_data){})
+struct hw_addr_data *hw_addr_set(struct hw_addr_data *addr, const uint8_t *bytes, size_t length);
+
void hw_addr_hash_func(const struct hw_addr_data *p, struct siphash *state);
int hw_addr_compare(const struct hw_addr_data *a, const struct hw_addr_data *b);
static inline bool hw_addr_equal(const struct hw_addr_data *a, const struct hw_addr_data *b) {
diff --git a/src/libnm-systemd-shared/src/basic/fd-util.c b/src/libnm-systemd-shared/src/basic/fd-util.c
index 53efeb401f..8029544570 100644
--- a/src/libnm-systemd-shared/src/basic/fd-util.c
+++ b/src/libnm-systemd-shared/src/basic/fd-util.c
@@ -5,7 +5,9 @@
#include <errno.h>
#include <fcntl.h>
#include <linux/btrfs.h>
+#if WANT_LINUX_FS_H
#include <linux/fs.h>
+#endif
#include <linux/magic.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
diff --git a/src/libnm-systemd-shared/src/basic/hash-funcs.c b/src/libnm-systemd-shared/src/basic/hash-funcs.c
index 3a02699ad9..eed30f0944 100644
--- a/src/libnm-systemd-shared/src/basic/hash-funcs.c
+++ b/src/libnm-systemd-shared/src/basic/hash-funcs.c
@@ -6,6 +6,7 @@
#include "hash-funcs.h"
#include "path-util.h"
+#include "strv.h"
void string_hash_func(const char *p, struct siphash *state) {
siphash24_compress(p, strlen(p) + 1, state);
@@ -17,6 +18,9 @@ DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(string_hash_ops_free,
DEFINE_HASH_OPS_FULL(string_hash_ops_free_free,
char, string_hash_func, string_compare_func, free,
void, free);
+DEFINE_HASH_OPS_FULL(string_hash_ops_free_strv_free,
+ char, string_hash_func, string_compare_func, free,
+ char*, strv_free);
#if 0 /* NM_IGNORED */
void path_hash_func(const char *q, struct siphash *state) {
diff --git a/src/libnm-systemd-shared/src/basic/hash-funcs.h b/src/libnm-systemd-shared/src/basic/hash-funcs.h
index c537c6af7e..c14302ec72 100644
--- a/src/libnm-systemd-shared/src/basic/hash-funcs.h
+++ b/src/libnm-systemd-shared/src/basic/hash-funcs.h
@@ -78,6 +78,7 @@ void string_hash_func(const char *p, struct siphash *state);
extern const struct hash_ops string_hash_ops;
extern const struct hash_ops string_hash_ops_free;
extern const struct hash_ops string_hash_ops_free_free;
+extern const struct hash_ops string_hash_ops_free_strv_free;
void path_hash_func(const char *p, struct siphash *state);
extern const struct hash_ops path_hash_ops;
diff --git a/src/libnm-systemd-shared/src/basic/hashmap.h b/src/libnm-systemd-shared/src/basic/hashmap.h
index eafc08f658..91b3fe862b 100644
--- a/src/libnm-systemd-shared/src/basic/hashmap.h
+++ b/src/libnm-systemd-shared/src/basic/hashmap.h
@@ -90,12 +90,7 @@ OrderedHashmap* _ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DE
#define ordered_hashmap_new(ops) _ordered_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS)
#define hashmap_free_and_replace(a, b) \
- ({ \
- hashmap_free(a); \
- (a) = (b); \
- (b) = NULL; \
- 0; \
- })
+ free_and_replace_full(a, b, hashmap_free)
HashmapBase* _hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value);
static inline Hashmap* hashmap_free(Hashmap *h) {
diff --git a/src/libnm-systemd-shared/src/basic/in-addr-util.c b/src/libnm-systemd-shared/src/basic/in-addr-util.c
index 74322f9a44..dc4446aeda 100644
--- a/src/libnm-systemd-shared/src/basic/in-addr-util.c
+++ b/src/libnm-systemd-shared/src/basic/in-addr-util.c
@@ -51,6 +51,20 @@ bool in4_addr_is_link_local(const struct in_addr *a) {
return (be32toh(a->s_addr) & UINT32_C(0xFFFF0000)) == (UINT32_C(169) << 24 | UINT32_C(254) << 16);
}
+bool in4_addr_is_link_local_dynamic(const struct in_addr *a) {
+ assert(a);
+
+ if (!in4_addr_is_link_local(a))
+ return false;
+
+ /* 169.254.0.0/24 and 169.254.255.0/24 must not be used for the dynamic IPv4LL assignment.
+ * See RFC 3927 Section 2.1:
+ * The IPv4 prefix 169.254/16 is registered with the IANA for this purpose. The first 256 and last
+ * 256 addresses in the 169.254/16 prefix are reserved for future use and MUST NOT be selected by a
+ * host using this dynamic configuration mechanism. */
+ return !IN_SET(be32toh(a->s_addr) & 0x0000FF00U, 0x0000U, 0xFF00U);
+}
+
bool in6_addr_is_link_local(const struct in6_addr *a) {
assert(a);
diff --git a/src/libnm-systemd-shared/src/basic/in-addr-util.h b/src/libnm-systemd-shared/src/basic/in-addr-util.h
index c1e7ef965d..fbc60436c7 100644
--- a/src/libnm-systemd-shared/src/basic/in-addr-util.h
+++ b/src/libnm-systemd-shared/src/basic/in-addr-util.h
@@ -44,6 +44,7 @@ static inline bool in_addr_data_is_set(const struct in_addr_data *a) {
int in_addr_is_multicast(int family, const union in_addr_union *u);
bool in4_addr_is_link_local(const struct in_addr *a);
+bool in4_addr_is_link_local_dynamic(const struct in_addr *a);
bool in6_addr_is_link_local(const struct in6_addr *a);
int in_addr_is_link_local(int family, const union in_addr_union *u);
bool in6_addr_is_link_local_all_nodes(const struct in6_addr *a);
diff --git a/src/libnm-systemd-shared/src/basic/list.h b/src/libnm-systemd-shared/src/basic/list.h
index 58e83a6cb2..ca30039690 100644
--- a/src/libnm-systemd-shared/src/basic/list.h
+++ b/src/libnm-systemd-shared/src/basic/list.h
@@ -170,9 +170,6 @@
i != (p); \
i = i->name##_next ? i->name##_next : (head))
-#define LIST_IS_EMPTY(head) \
- (!(head))
-
/* Join two lists tail to head: a->b, c->d to a->b->c->d and de-initialise second list */
#define LIST_JOIN(name,a,b) \
do { \
diff --git a/src/libnm-systemd-shared/src/basic/macro.h b/src/libnm-systemd-shared/src/basic/macro.h
index 630aad6464..7380da1093 100644
--- a/src/libnm-systemd-shared/src/basic/macro.h
+++ b/src/libnm-systemd-shared/src/basic/macro.h
@@ -88,10 +88,6 @@
_Pragma("GCC diagnostic push")
#endif
-#define DISABLE_WARNING_FLOAT_EQUAL \
- _Pragma("GCC diagnostic push"); \
- _Pragma("GCC diagnostic ignored \"-Wfloat-equal\"")
-
#define DISABLE_WARNING_TYPE_LIMITS \
_Pragma("GCC diagnostic push"); \
_Pragma("GCC diagnostic ignored \"-Wtype-limits\"")
diff --git a/src/libnm-systemd-shared/src/basic/path-util.c b/src/libnm-systemd-shared/src/basic/path-util.c
index 244336c1af..3ba3510fce 100644
--- a/src/libnm-systemd-shared/src/basic/path-util.c
+++ b/src/libnm-systemd-shared/src/basic/path-util.c
@@ -1061,7 +1061,7 @@ int path_extract_filename(const char *path, char **ret) {
return -ENOMEM;
*ret = TAKE_PTR(a);
- return strlen(c) > (size_t)r ? O_DIRECTORY : 0;
+ return strlen(c) > (size_t) r ? O_DIRECTORY : 0;
}
int path_extract_directory(const char *path, char **ret) {
@@ -1115,7 +1115,7 @@ bool filename_is_valid(const char *p) {
if (isempty(p))
return false;
- if (dot_or_dot_dot(p))
+ if (dot_or_dot_dot(p)) /* Yes, in this context we consider "." and ".." invalid */
return false;
e = strchrnul(p, '/');
diff --git a/src/libnm-systemd-shared/src/basic/path-util.h b/src/libnm-systemd-shared/src/basic/path-util.h
index 6f8bf116ff..c97c4540d3 100644
--- a/src/libnm-systemd-shared/src/basic/path-util.h
+++ b/src/libnm-systemd-shared/src/basic/path-util.h
@@ -45,12 +45,16 @@
#endif
static inline bool is_path(const char *p) {
- assert(p);
+ if (!p) /* A NULL pointer is definitely not a path */
+ return false;
+
return strchr(p, '/');
}
static inline bool path_is_absolute(const char *p) {
- assert(p);
+ if (!p) /* A NULL pointer is definitely not an absolute path */
+ return false;
+
return p[0] == '/';
}
@@ -159,10 +163,10 @@ int path_extract_directory(const char *path, char **ret);
bool filename_is_valid(const char *p) _pure_;
bool path_is_valid_full(const char *p, bool accept_dot_dot) _pure_;
static inline bool path_is_valid(const char *p) {
- return path_is_valid_full(p, true);
+ return path_is_valid_full(p, /* accept_dot_dot= */ true);
}
static inline bool path_is_safe(const char *p) {
- return path_is_valid_full(p, false);
+ return path_is_valid_full(p, /* accept_dot_dot= */ false);
}
bool path_is_normalized(const char *p) _pure_;
diff --git a/src/libnm-systemd-shared/src/basic/process-util.c b/src/libnm-systemd-shared/src/basic/process-util.c
index bb3afe0b4e..1c23a2f8f6 100644
--- a/src/libnm-systemd-shared/src/basic/process-util.c
+++ b/src/libnm-systemd-shared/src/basic/process-util.c
@@ -1156,7 +1156,7 @@ void reset_cached_pid(void) {
pid_t getpid_cached(void) {
static bool installed = false;
- pid_t current_value;
+ pid_t current_value = CACHED_PID_UNSET;
/* getpid_cached() is much like getpid(), but caches the value in local memory, to avoid having to invoke a
* system call each time. This restores glibc behaviour from before 2.24, when getpid() was unconditionally
@@ -1167,7 +1167,13 @@ pid_t getpid_cached(void) {
* https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=c579f48edba88380635ab98cb612030e3ed8691e
*/
- current_value = __sync_val_compare_and_swap(&cached_pid, CACHED_PID_UNSET, CACHED_PID_BUSY);
+ __atomic_compare_exchange_n(
+ &cached_pid,
+ &current_value,
+ CACHED_PID_BUSY,
+ false,
+ __ATOMIC_SEQ_CST,
+ __ATOMIC_SEQ_CST);
switch (current_value) {
@@ -1589,6 +1595,30 @@ bool invoked_as(char *argv[], const char *token) {
return strstr(last_path_component(argv[0]), token);
}
+bool invoked_by_systemd(void) {
+ int r;
+
+ /* If the process is directly executed by PID1 (e.g. ExecStart= or generator), systemd-importd,
+ * or systemd-homed, then $SYSTEMD_EXEC_PID= is set, and read the command line. */
+ const char *e = getenv("SYSTEMD_EXEC_PID");
+ if (!e)
+ return false;
+
+ if (streq(e, "*"))
+ /* For testing. */
+ return true;
+
+ pid_t p;
+ r = parse_pid(e, &p);
+ if (r < 0) {
+ /* We know that systemd sets the variable correctly. Something else must have set it. */
+ log_debug_errno(r, "Failed to parse \"SYSTEMD_EXEC_PID=%s\", ignoring: %m", e);
+ return false;
+ }
+
+ return getpid_cached() == p;
+}
+
_noreturn_ void freeze(void) {
log_close();
diff --git a/src/libnm-systemd-shared/src/basic/process-util.h b/src/libnm-systemd-shared/src/basic/process-util.h
index c488c6a833..962f12d11c 100644
--- a/src/libnm-systemd-shared/src/basic/process-util.h
+++ b/src/libnm-systemd-shared/src/basic/process-util.h
@@ -192,6 +192,8 @@ int setpriority_closest(int priority);
bool invoked_as(char *argv[], const char *token);
+bool invoked_by_systemd(void);
+
_noreturn_ void freeze(void);
bool argv_looks_like_help(int argc, char **argv);
diff --git a/src/libnm-systemd-shared/src/basic/set.h b/src/libnm-systemd-shared/src/basic/set.h
index 52cf63e2dd..618e729744 100644
--- a/src/libnm-systemd-shared/src/basic/set.h
+++ b/src/libnm-systemd-shared/src/basic/set.h
@@ -6,12 +6,7 @@
#include "macro.h"
#define set_free_and_replace(a, b) \
- ({ \
- set_free(a); \
- (a) = (b); \
- (b) = NULL; \
- 0; \
- })
+ free_and_replace_full(a, b, set_free)
Set* _set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
#define set_new(ops) _set_new(ops HASHMAP_DEBUG_SRC_ARGS)
diff --git a/src/libnm-systemd-shared/src/basic/stat-util.c b/src/libnm-systemd-shared/src/basic/stat-util.c
index f2041535f4..8c5858ffed 100644
--- a/src/libnm-systemd-shared/src/basic/stat-util.c
+++ b/src/libnm-systemd-shared/src/basic/stat-util.c
@@ -39,16 +39,17 @@ int is_symlink(const char *path) {
}
#endif /* NM_IGNORED */
-int is_dir(const char* path, bool follow) {
+int is_dir_full(int atfd, const char* path, bool follow) {
struct stat st;
int r;
- assert(path);
+ assert(atfd >= 0 || atfd == AT_FDCWD);
+ assert(atfd >= 0 || path);
- if (follow)
- r = stat(path, &st);
+ if (path)
+ r = fstatat(atfd, path, &st, follow ? 0 : AT_SYMLINK_NOFOLLOW);
else
- r = lstat(path, &st);
+ r = fstat(atfd, &st);
if (r < 0)
return -errno;
@@ -56,15 +57,6 @@ int is_dir(const char* path, bool follow) {
}
#if 0 /* NM_IGNORED */
-int is_dir_fd(int fd) {
- struct stat st;
-
- if (fstat(fd, &st) < 0)
- return -errno;
-
- return !!S_ISDIR(st.st_mode);
-}
-
int is_device_node(const char *path) {
struct stat info;
diff --git a/src/libnm-systemd-shared/src/basic/stat-util.h b/src/libnm-systemd-shared/src/basic/stat-util.h
index 7f0b3dc0af..56f15534aa 100644
--- a/src/libnm-systemd-shared/src/basic/stat-util.h
+++ b/src/libnm-systemd-shared/src/basic/stat-util.h
@@ -13,8 +13,13 @@
#include "missing_stat.h"
int is_symlink(const char *path);
-int is_dir(const char *path, bool follow);
-int is_dir_fd(int fd);
+int is_dir_full(int atfd, const char *fname, bool follow);
+static inline int is_dir(const char *path, bool follow) {
+ return is_dir_full(AT_FDCWD, path, follow);
+}
+static inline int is_dir_fd(int fd) {
+ return is_dir_full(fd, NULL, false);
+}
int is_device_node(const char *path);
int dir_is_empty_at(int dir_fd, const char *path, bool ignore_hidden_or_backup);
diff --git a/src/libnm-systemd-shared/src/basic/strv.h b/src/libnm-systemd-shared/src/basic/strv.h
index 072739df35..87ec6337bd 100644
--- a/src/libnm-systemd-shared/src/basic/strv.h
+++ b/src/libnm-systemd-shared/src/basic/strv.h
@@ -258,14 +258,7 @@ int strv_extend_n(char ***l, const char *value, size_t n);
int fputstrv(FILE *f, char * const *l, const char *separator, bool *space);
#define strv_free_and_replace(a, b) \
- ({ \
- char ***_a = &(a); \
- char ***_b = &(b); \
- strv_free(*_a); \
- (*_a) = (*_b); \
- (*_b) = NULL; \
- 0; \
- })
+ free_and_replace_full(a, b, strv_free)
extern const struct hash_ops string_strv_hash_ops;
int _string_strv_hashmap_put(Hashmap **h, const char *key, const char *value HASHMAP_DEBUG_PARAMS);
diff --git a/src/libnm-systemd-shared/src/basic/time-util.c b/src/libnm-systemd-shared/src/basic/time-util.c
index 0496ede3ee..0c8f49292f 100644
--- a/src/libnm-systemd-shared/src/basic/time-util.c
+++ b/src/libnm-systemd-shared/src/basic/time-util.c
@@ -595,7 +595,7 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
t = b;
}
- n = MIN((size_t) k, l);
+ n = MIN((size_t) k, l-1);
l -= n;
p += n;
diff --git a/src/libnm-systemd-shared/src/fundamental/macro-fundamental.h b/src/libnm-systemd-shared/src/fundamental/macro-fundamental.h
index a738b1f50e..0ed9940311 100644
--- a/src/libnm-systemd-shared/src/fundamental/macro-fundamental.h
+++ b/src/libnm-systemd-shared/src/fundamental/macro-fundamental.h
@@ -95,6 +95,20 @@
_expr_; \
})
+#define ASSERT_NONNEG(expr) \
+ ({ \
+ typeof(expr) _expr_ = (expr), _zero = 0; \
+ assert(_expr_ >= _zero); \
+ _expr_; \
+ })
+
+#define ASSERT_SE_NONNEG(expr) \
+ ({ \
+ typeof(expr) _expr_ = (expr), _zero = 0; \
+ assert_se(_expr_ >= _zero); \
+ _expr_; \
+ })
+
#define assert_cc(expr) static_assert(expr, #expr)
@@ -106,10 +120,10 @@
* on this macro will run concurrently to all other code conditionalized
* the same way, there's no ordering or completion enforced. */
#define ONCE __ONCE(UNIQ_T(_once_, UNIQ))
-#define __ONCE(o) \
- ({ \
- static bool (o) = false; \
- __sync_bool_compare_and_swap(&(o), false, true); \
+#define __ONCE(o) \
+ ({ \
+ static bool (o) = false; \
+ __atomic_exchange_n(&(o), true, __ATOMIC_SEQ_CST); \
})
#undef MAX
@@ -186,6 +200,27 @@
MIN(_c, z); \
})
+/* Returns true if the passed integer is a positive power of two */
+#define CONST_ISPOWEROF2(x) \
+ ((x) > 0 && ((x) & ((x) - 1)) == 0)
+
+#if 0 /* NM_IGNORED */
+#define ISPOWEROF2(x) \
+ __builtin_choose_expr( \
+ __builtin_constant_p(x), \
+ CONST_ISPOWEROF2(x), \
+ ({ \
+ const typeof(x) _x = (x); \
+ CONST_ISPOWEROF2(_x); \
+ }))
+#else /* NM_IGNORED */
+#define ISPOWEROF2(x) \
+ ({ \
+ const typeof(x) _x = (x); \
+ CONST_ISPOWEROF2(_x); \
+ })
+#endif /* NM_IGNORED */
+
#define LESS_BY(a, b) __LESS_BY(UNIQ, (a), UNIQ, (b))
#define __LESS_BY(aq, a, bq, b) \
({ \
@@ -300,16 +335,7 @@
})
static inline size_t ALIGN_TO(size_t l, size_t ali) {
- /* Check that alignment is exponent of 2 */
-#if SIZE_MAX == UINT_MAX
- assert(__builtin_popcount(ali) == 1);
-#elif SIZE_MAX == ULONG_MAX
- assert(__builtin_popcountl(ali) == 1);
-#elif SIZE_MAX == ULLONG_MAX
- assert(__builtin_popcountll(ali) == 1);
-#else
- #error "Unexpected size_t"
-#endif
+ assert(ISPOWEROF2(ali));
if (l > SIZE_MAX - (ali - 1))
return SIZE_MAX; /* indicate overflow */
@@ -330,7 +356,7 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
__builtin_choose_expr( \
__builtin_constant_p(l) && \
__builtin_constant_p(ali) && \
- __builtin_popcountll(ali) == 1 && /* is power of 2? */ \
+ CONST_ISPOWEROF2(ali) && \
(l <= SIZE_MAX - (ali - 1)), /* overflow? */ \
((l) + (ali) - 1) & ~((ali) - 1), \
VOID_0)