summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2021-06-17 16:48:12 +0200
committerThomas Haller <thaller@redhat.com>2021-06-23 13:47:39 +0200
commitfbf39522741bb5ffb8bdaef991486e3eb942f1a2 (patch)
tree8042706a18e0f00612ded50e2f428bd2a72d79d6
parentacd1a54d8f14680fc3bcd79f7fff55e6700d1d10 (diff)
parent02a4e00d562e8e73d7ede7644009e4327617b1c2 (diff)
systemd: merge branch systemd into main
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/897
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.c51
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.h2
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/dhcp-internal.h4
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/dhcp6-internal.h4
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-client.c16
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c14
-rw-r--r--src/libnm-systemd-core/src/libsystemd/sd-event/sd-event.c128
-rw-r--r--src/libnm-systemd-core/src/systemd/sd-id128.h7
-rw-r--r--src/libnm-systemd-shared/src/basic/alloc-util.h7
-rw-r--r--src/libnm-systemd-shared/src/basic/ether-addr-util.c17
-rw-r--r--src/libnm-systemd-shared/src/basic/ether-addr-util.h30
-rw-r--r--src/libnm-systemd-shared/src/basic/fileio.c25
-rw-r--r--src/libnm-systemd-shared/src/basic/fs-util.c2
-rw-r--r--src/libnm-systemd-shared/src/basic/fs-util.h2
-rw-r--r--src/libnm-systemd-shared/src/basic/hexdecoct.c10
-rw-r--r--src/libnm-systemd-shared/src/basic/hexdecoct.h1
-rw-r--r--src/libnm-systemd-shared/src/basic/in-addr-util.c6
-rw-r--r--src/libnm-systemd-shared/src/basic/in-addr-util.h1
-rw-r--r--src/libnm-systemd-shared/src/basic/path-util.c8
-rw-r--r--src/libnm-systemd-shared/src/basic/process-util.c2
-rw-r--r--src/libnm-systemd-shared/src/basic/random-util.c2
-rw-r--r--src/libnm-systemd-shared/src/basic/socket-util.c4
-rw-r--r--src/libnm-systemd-shared/src/basic/time-util.c10
-rw-r--r--src/libnm-systemd-shared/src/fundamental/string-util-fundamental.c12
24 files changed, 225 insertions, 140 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 0720e38185..bd47ff41ef 100644
--- a/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.c
+++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.c
@@ -14,6 +14,7 @@
#include "network-util.h"
#include "siphash24.h"
#include "sparse-endian.h"
+#include "stat-util.h"
#include "stdio-util.h"
#include "udev-util.h"
#include "virt.h"
@@ -166,38 +167,40 @@ int dhcp_identifier_set_iaid(
const uint8_t *mac,
size_t mac_len,
bool legacy_unstable_byteorder,
+ bool use_mac,
void *_id) {
#if 0 /* NM_IGNORED */
+
/* name is a pointer to memory in the sd_device struct, so must
* have the same scope */
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
const char *name = NULL;
- uint64_t id;
uint32_t id32;
+ uint64_t id;
+ int r;
+
+ if (path_is_read_only_fs("/sys") <= 0 && !use_mac) {
+ /* udev should be around */
+
+ r = sd_device_new_from_ifindex(&device, ifindex);
+ if (r < 0)
+ return r;
+
+ r = sd_device_get_is_initialized(device);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ /* not yet ready */
+ return -EBUSY;
+
+ r = device_is_renaming(device);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ /* device is under renaming */
+ return -EBUSY;
- if (detect_container() <= 0) {
- /* not in a container, udev will be around */
- char ifindex_str[1 + DECIMAL_STR_MAX(int)];
- int r;
-
- xsprintf(ifindex_str, "n%d", ifindex);
- if (sd_device_new_from_device_id(&device, ifindex_str) >= 0) {
- r = sd_device_get_is_initialized(device);
- if (r < 0)
- return r;
- if (r == 0)
- /* not yet ready */
- return -EBUSY;
-
- r = device_is_renaming(device);
- if (r < 0)
- return r;
- if (r > 0)
- /* device is under renaming */
- return -EBUSY;
-
- name = net_get_name_persistent(device);
- }
+ name = net_get_name_persistent(device);
}
if (name)
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 1d9a9c55ba..6c24af0326 100644
--- a/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.h
+++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.h
@@ -59,4 +59,4 @@ int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *add
int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len);
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len);
int dhcp_identifier_set_duid_uuid(struct duid *duid, size_t *len);
-int dhcp_identifier_set_iaid(int ifindex, const uint8_t *mac, size_t mac_len, bool legacy_unstable_byteorder, void *_id);
+int dhcp_identifier_set_iaid(int ifindex, const uint8_t *mac, size_t mac_len, bool legacy_unstable_byteorder, bool use_mac, void *_id);
diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp-internal.h b/src/libnm-systemd-core/src/libsystemd-network/dhcp-internal.h
index d8c42757aa..16999971d2 100644
--- a/src/libnm-systemd-core/src/libsystemd-network/dhcp-internal.h
+++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp-internal.h
@@ -30,6 +30,8 @@ typedef struct DHCPServerData {
extern const struct hash_ops dhcp_option_hash_ops;
+typedef struct sd_dhcp_client sd_dhcp_client;
+
int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, uint32_t xid,
const uint8_t *mac_addr, size_t mac_addr_len,
const uint8_t *bcast_addr, size_t bcast_addr_len,
@@ -62,6 +64,8 @@ void dhcp_packet_append_ip_headers(DHCPPacket *packet, be32_t source_addr,
int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum, uint16_t port);
+void dhcp_client_set_test_mode(sd_dhcp_client *client, bool test_mode);
+
/* If we are invoking callbacks of a dhcp-client, ensure unreffing the
* client from the callback doesn't destroy the object we are working
* on */
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 34e1f61cb0..f0f814957f 100644
--- a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-internal.h
+++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-internal.h
@@ -91,6 +91,8 @@ typedef struct DHCP6IA {
LIST_HEAD(DHCP6Address, addresses);
} DHCP6IA;
+typedef struct sd_dhcp6_client sd_dhcp6_client;
+
int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
size_t optlen, const void *optval);
int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia);
@@ -118,6 +120,8 @@ int dhcp6_message_type_from_string(const char *s) _pure_;
const char *dhcp6_message_status_to_string(int s) _const_;
int dhcp6_message_status_from_string(const char *s) _pure_;
+void dhcp6_client_set_test_mode(sd_dhcp6_client *client, bool test_mode);
+
#define log_dhcp6_client_errno(client, error, fmt, ...) \
log_interface_prefix_full_errno( \
"DHCPv6 client: ", \
diff --git a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-client.c b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-client.c
index 94e43da395..f23b398e12 100644
--- a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-client.c
@@ -119,6 +119,9 @@ struct sd_dhcp_client {
sd_dhcp_lease *lease;
usec_t start_delay;
int ip_service_type;
+
+ /* Ignore ifindex when generating iaid. See dhcp_identifier_set_iaid(). */
+ bool test_mode;
};
static const uint8_t default_req_opts[] = {
@@ -470,7 +473,8 @@ static int dhcp_client_set_iaid_duid_internal(
else {
r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr,
client->mac_addr_len,
- true,
+ /* legacy_unstable_byteorder = */ true,
+ /* use_mac = */ client->test_mode,
&client->client_id.ns.iaid);
if (r < 0)
return log_dhcp_client_errno(client, r, "Failed to set IAID: %m");
@@ -560,6 +564,12 @@ int sd_dhcp_client_set_duid_llt(
}
#endif /* NM_IGNORED */
+void dhcp_client_set_test_mode(sd_dhcp_client *client, bool test_mode) {
+ assert(client);
+
+ client->test_mode = test_mode;
+}
+
int sd_dhcp_client_set_hostname(
sd_dhcp_client *client,
const char *hostname) {
@@ -865,7 +875,9 @@ static int client_message_init(
client->client_id.type = 255;
r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len,
- true, &client->client_id.ns.iaid);
+ /* legacy_unstable_byteorder = */ true,
+ /* use_mac = */ client->test_mode,
+ &client->client_id.ns.iaid);
if (r < 0)
return r;
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 888dfa2d6b..ae1f4a191f 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
@@ -90,6 +90,9 @@ struct sd_dhcp6_client {
usec_t information_refresh_time_usec;
OrderedHashmap *extra_options;
OrderedHashmap *vendor_options;
+
+ /* Ignore ifindex when generating iaid. See dhcp_identifier_set_iaid(). */
+ bool test_mode;
};
static const uint16_t default_req_opts[] = {
@@ -408,6 +411,12 @@ int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid) {
return 0;
}
+void dhcp6_client_set_test_mode(sd_dhcp6_client *client, bool test_mode) {
+ assert(client);
+
+ client->test_mode = test_mode;
+}
+
int sd_dhcp6_client_get_iaid(sd_dhcp6_client *client, uint32_t *iaid) {
assert_return(client, -EINVAL);
assert_return(iaid, -EINVAL);
@@ -1083,7 +1092,10 @@ static int client_ensure_iaid(sd_dhcp6_client *client) {
if (client->iaid_set)
return 0;
- r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, true, &iaid);
+ r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len,
+ /* legacy_unstable_byteorder = */ true,
+ /* use_mac = */ client->test_mode,
+ &iaid);
if (r < 0)
return r;
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 4492674481..2b81bfa100 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
@@ -170,10 +170,9 @@ static int pending_prioq_compare(const void *a, const void *b) {
assert(y->pending);
/* Enabled ones first */
- if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
- return -1;
- if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
- return 1;
+ r = CMP(x->enabled == SD_EVENT_OFF, y->enabled == SD_EVENT_OFF);
+ if (r != 0)
+ return r;
/* Non rate-limited ones first. */
r = CMP(!!x->ratelimited, !!y->ratelimited);
@@ -197,10 +196,9 @@ static int prepare_prioq_compare(const void *a, const void *b) {
assert(y->prepare);
/* Enabled ones first */
- if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
- return -1;
- if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
- return 1;
+ r = CMP(x->enabled == SD_EVENT_OFF, y->enabled == SD_EVENT_OFF);
+ if (r != 0)
+ return r;
/* Non rate-limited ones first. */
r = CMP(!!x->ratelimited, !!y->ratelimited);
@@ -239,25 +237,6 @@ static usec_t time_event_source_next(const sd_event_source *s) {
return USEC_INFINITY;
}
-static int earliest_time_prioq_compare(const void *a, const void *b) {
- const sd_event_source *x = a, *y = b;
-
- /* Enabled ones first */
- if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
- return -1;
- if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
- return 1;
-
- /* Move the pending ones to the end */
- if (!x->pending && y->pending)
- return -1;
- if (x->pending && !y->pending)
- return 1;
-
- /* Order by time */
- return CMP(time_event_source_next(x), time_event_source_next(y));
-}
-
static usec_t time_event_source_latest(const sd_event_source *s) {
assert(s);
@@ -276,36 +255,51 @@ static usec_t time_event_source_latest(const sd_event_source *s) {
return USEC_INFINITY;
}
-static int latest_time_prioq_compare(const void *a, const void *b) {
+static bool event_source_timer_candidate(const sd_event_source *s) {
+ assert(s);
+
+ /* Returns true for event sources that either are not pending yet (i.e. where it's worth to mark them pending)
+ * or which are currently ratelimited (i.e. where it's worth leaving the ratelimited state) */
+ return !s->pending || s->ratelimited;
+}
+
+static int time_prioq_compare(const void *a, const void *b, usec_t (*time_func)(const sd_event_source *s)) {
const sd_event_source *x = a, *y = b;
+ int r;
/* Enabled ones first */
- if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
- return -1;
- if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
- return 1;
+ r = CMP(x->enabled == SD_EVENT_OFF, y->enabled == SD_EVENT_OFF);
+ if (r != 0)
+ return r;
- /* Move the pending ones to the end */
- if (!x->pending && y->pending)
- return -1;
- if (x->pending && !y->pending)
- return 1;
+ /* Order "non-pending OR ratelimited" before "pending AND not-ratelimited" */
+ r = CMP(!event_source_timer_candidate(x), !event_source_timer_candidate(y));
+ if (r != 0)
+ return r;
/* Order by time */
- return CMP(time_event_source_latest(x), time_event_source_latest(y));
+ return CMP(time_func(x), time_func(y));
+}
+
+static int earliest_time_prioq_compare(const void *a, const void *b) {
+ return time_prioq_compare(a, b, time_event_source_next);
+}
+
+static int latest_time_prioq_compare(const void *a, const void *b) {
+ return time_prioq_compare(a, b, time_event_source_latest);
}
static int exit_prioq_compare(const void *a, const void *b) {
const sd_event_source *x = a, *y = b;
+ int r;
assert(x->type == SOURCE_EXIT);
assert(y->type == SOURCE_EXIT);
/* Enabled ones first */
- if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
- return -1;
- if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
- return 1;
+ r = CMP(x->enabled == SD_EVENT_OFF, y->enabled == SD_EVENT_OFF);
+ if (r != 0)
+ return r;
/* Lower priority values first */
return CMP(x->priority, y->priority);
@@ -779,14 +773,15 @@ static void event_source_time_prioq_reshuffle(sd_event_source *s) {
assert(s);
/* Called whenever the event source's timer ordering properties changed, i.e. time, accuracy,
- * pending, enable state. Makes sure the two prioq's are ordered properly again. */
+ * pending, enable state, and ratelimiting state. Makes sure the two prioq's are ordered
+ * properly again. */
if (s->ratelimited)
d = &s->event->monotonic;
- else {
- assert(EVENT_SOURCE_IS_TIME(s->type));
+ else if (EVENT_SOURCE_IS_TIME(s->type))
assert_se(d = event_get_clock_data(s->event, s->type));
- }
+ else
+ return; /* no-op for an event source which is neither a timer nor ratelimited. */
prioq_reshuffle(d->earliest, s, &s->earliest_index);
prioq_reshuffle(d->latest, s, &s->latest_index);
@@ -2379,14 +2374,6 @@ static int event_source_offline(
source_io_unregister(s);
break;
- case SOURCE_TIME_REALTIME:
- case SOURCE_TIME_BOOTTIME:
- case SOURCE_TIME_MONOTONIC:
- case SOURCE_TIME_REALTIME_ALARM:
- case SOURCE_TIME_BOOTTIME_ALARM:
- event_source_time_prioq_reshuffle(s);
- break;
-
case SOURCE_SIGNAL:
event_gc_signal_data(s->event, &s->priority, s->signal.sig);
break;
@@ -2407,6 +2394,11 @@ static int event_source_offline(
prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
break;
+ case SOURCE_TIME_REALTIME:
+ case SOURCE_TIME_BOOTTIME:
+ case SOURCE_TIME_MONOTONIC:
+ case SOURCE_TIME_REALTIME_ALARM:
+ case SOURCE_TIME_BOOTTIME_ALARM:
case SOURCE_DEFER:
case SOURCE_POST:
case SOURCE_INOTIFY:
@@ -2416,6 +2408,9 @@ static int event_source_offline(
assert_not_reached("Wut? I shouldn't exist.");
}
+ /* Always reshuffle time prioq, as the ratelimited flag may be changed. */
+ event_source_time_prioq_reshuffle(s);
+
return 1;
}
@@ -2505,22 +2500,11 @@ static int event_source_online(
s->ratelimited = ratelimited;
/* Non-failing operations below */
- switch (s->type) {
- case SOURCE_TIME_REALTIME:
- case SOURCE_TIME_BOOTTIME:
- case SOURCE_TIME_MONOTONIC:
- case SOURCE_TIME_REALTIME_ALARM:
- case SOURCE_TIME_BOOTTIME_ALARM:
- event_source_time_prioq_reshuffle(s);
- break;
-
- case SOURCE_EXIT:
+ if (s->type == SOURCE_EXIT)
prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
- break;
- default:
- break;
- }
+ /* Always reshuffle time prioq, as the ratelimited flag may be changed. */
+ event_source_time_prioq_reshuffle(s);
return 1;
}
@@ -2990,8 +2974,8 @@ static int event_arm_timer(
if (!d->needs_rearm)
return 0;
- else
- d->needs_rearm = false;
+
+ d->needs_rearm = false;
a = prioq_peek(d->earliest);
if (!a || a->enabled == SD_EVENT_OFF || time_event_source_next(a) == USEC_INFINITY) {
@@ -3687,8 +3671,8 @@ static int arm_watchdog(sd_event *e) {
assert(e->watchdog_fd >= 0);
t = sleep_between(e,
- e->watchdog_last + (e->watchdog_period / 2),
- e->watchdog_last + (e->watchdog_period * 3 / 4));
+ usec_add(e->watchdog_last, (e->watchdog_period / 2)),
+ usec_add(e->watchdog_last, (e->watchdog_period * 3 / 4)));
timespec_store(&its.it_value, t);
diff --git a/src/libnm-systemd-core/src/systemd/sd-id128.h b/src/libnm-systemd-core/src/systemd/sd-id128.h
index ab209c8c7d..f2dd7357f8 100644
--- a/src/libnm-systemd-core/src/systemd/sd-id128.h
+++ b/src/libnm-systemd-core/src/systemd/sd-id128.h
@@ -63,7 +63,9 @@ int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret);
#define SD_ID128_FORMAT_STR "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
#define SD_ID128_FORMAT_VAL(x) (x).bytes[0], (x).bytes[1], (x).bytes[2], (x).bytes[3], (x).bytes[4], (x).bytes[5], (x).bytes[6], (x).bytes[7], (x).bytes[8], (x).bytes[9], (x).bytes[10], (x).bytes[11], (x).bytes[12], (x).bytes[13], (x).bytes[14], (x).bytes[15]
-/* Like SD_ID128_FORMAT_STR, but formats as UUID, not in plain format */
+/* Like SD_ID128_FORMAT_STR, but formats as UUID, not in plain format (Strictly Big Endian byte order,
+ * i.e. treats everything as RFC4122 Variant 1 UUIDs, even if variant says otherwise, but matching other
+ * Linux userspace behaviour.) */
#define SD_ID128_UUID_FORMAT_STR "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
#define SD_ID128_CONST_STR(x) \
@@ -105,6 +107,9 @@ int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret);
#define SD_ID128_MAKE_STR(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \
#a #b #c #d #e #f #g #h #i #j #k #l #m #n #o #p
+#define SD_ID128_MAKE_UUID_STR(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \
+ #a #b #c #d "-" #e #f "-" #g #h "-" #i #j "-" #k #l #m #n #o #p
+
_sd_pure_ static __inline__ int sd_id128_equal(sd_id128_t a, sd_id128_t b) {
return memcmp(&a, &b, 16) == 0;
}
diff --git a/src/libnm-systemd-shared/src/basic/alloc-util.h b/src/libnm-systemd-shared/src/basic/alloc-util.h
index 99fbd3a889..3c33308f48 100644
--- a/src/libnm-systemd-shared/src/basic/alloc-util.h
+++ b/src/libnm-systemd-shared/src/basic/alloc-util.h
@@ -79,6 +79,13 @@ void* memdup_suffix0(const void *p, size_t l); /* We can't use _alloc_() here, s
memcpy_safe(_q_, p, _l_); \
})
+static inline void unsetp(void *p) {
+ /* A trivial "destructor" that can be used in cases where we want to
+ * unset a pointer from a _cleanup_ function. */
+
+ *(void**)p = NULL;
+}
+
static inline void freep(void *p) {
*(void**)p = mfree(*(void**) p);
}
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 f60e1042a0..10acb25849 100644
--- a/src/libnm-systemd-shared/src/basic/ether-addr-util.c
+++ b/src/libnm-systemd-shared/src/basic/ether-addr-util.c
@@ -12,13 +12,13 @@
#include "macro.h"
#include "string-util.h"
-char* hw_addr_to_string(const hw_addr_data *addr, char buffer[HW_ADDR_TO_STRING_MAX]) {
+char* hw_addr_to_string(const struct hw_addr_data *addr, char buffer[HW_ADDR_TO_STRING_MAX]) {
assert(addr);
assert(buffer);
assert(addr->length <= HW_ADDR_MAX_SIZE);
for (size_t i = 0; i < addr->length; i++) {
- sprintf(&buffer[3*i], "%02"PRIx8, addr->addr.bytes[i]);
+ sprintf(&buffer[3*i], "%02"PRIx8, addr->bytes[i]);
if (i < addr->length - 1)
buffer[3*i + 2] = ':';
}
@@ -26,6 +26,19 @@ char* hw_addr_to_string(const hw_addr_data *addr, char buffer[HW_ADDR_TO_STRING_
return buffer;
}
+int hw_addr_compare(const struct hw_addr_data *a, const struct hw_addr_data *b) {
+ int r;
+
+ assert(a);
+ assert(b);
+
+ r = CMP(a->length, b->length);
+ if (r != 0)
+ return r;
+
+ return memcmp(a->bytes, b->bytes, a->length);
+}
+
char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]) {
assert(addr);
assert(buffer);
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 712c927796..cf8afff356 100644
--- a/src/libnm-systemd-shared/src/basic/ether-addr-util.h
+++ b/src/libnm-systemd-shared/src/basic/ether-addr-util.h
@@ -11,24 +11,30 @@
* defines a macro of the same name with a much lower size. */
#define HW_ADDR_MAX_SIZE 32
-union hw_addr_union {
- struct ether_addr ether;
- uint8_t infiniband[INFINIBAND_ALEN];
- uint8_t bytes[HW_ADDR_MAX_SIZE];
-};
-
-typedef struct hw_addr_data {
- union hw_addr_union addr;
+struct hw_addr_data {
size_t length;
-} hw_addr_data;
+ union {
+ struct ether_addr ether;
+ uint8_t infiniband[INFINIBAND_ALEN];
+ uint8_t bytes[HW_ADDR_MAX_SIZE];
+ };
+};
#define HW_ADDR_TO_STRING_MAX (3*HW_ADDR_MAX_SIZE)
-char* hw_addr_to_string(const hw_addr_data *addr, char buffer[HW_ADDR_TO_STRING_MAX]);
+char* hw_addr_to_string(const struct hw_addr_data *addr, char buffer[HW_ADDR_TO_STRING_MAX]);
/* Use only as function argument, never stand-alone! */
#define HW_ADDR_TO_STR(hw_addr) hw_addr_to_string((hw_addr), (char[HW_ADDR_TO_STRING_MAX]){})
-#define HW_ADDR_NULL ((const hw_addr_data){})
+#define HW_ADDR_NULL ((const struct hw_addr_data){})
+
+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) {
+ return hw_addr_compare(a, b) == 0;
+}
+static inline bool hw_addr_is_null(const struct hw_addr_data *addr) {
+ return hw_addr_equal(addr, &HW_ADDR_NULL);
+}
#define ETHER_ADDR_FORMAT_STR "%02X%02X%02X%02X%02X%02X"
#define ETHER_ADDR_FORMAT_VAL(x) (x).ether_addr_octet[0], (x).ether_addr_octet[1], (x).ether_addr_octet[2], (x).ether_addr_octet[3], (x).ether_addr_octet[4], (x).ether_addr_octet[5]
@@ -36,6 +42,8 @@ char* hw_addr_to_string(const hw_addr_data *addr, char buffer[HW_ADDR_TO_STRING_
#define ETHER_ADDR_TO_STRING_MAX (3*6)
char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]);
int ether_addr_to_string_alloc(const struct ether_addr *addr, char **ret);
+/* Use only as function argument, never stand-alone! */
+#define ETHER_ADDR_TO_STR(addr) ether_addr_to_string((addr), (char[ETHER_ADDR_TO_STRING_MAX]){})
int ether_addr_compare(const struct ether_addr *a, const struct ether_addr *b);
static inline bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b) {
diff --git a/src/libnm-systemd-shared/src/basic/fileio.c b/src/libnm-systemd-shared/src/basic/fileio.c
index de78f70ee6..c19b0ceeba 100644
--- a/src/libnm-systemd-shared/src/basic/fileio.c
+++ b/src/libnm-systemd-shared/src/basic/fileio.c
@@ -29,8 +29,17 @@
#include "string-util.h"
#include "tmpfile-util.h"
-/* The maximum size of the file we'll read in one go. */
-#define READ_FULL_BYTES_MAX (4U*1024U*1024U - 1)
+/* The maximum size of the file we'll read in one go in read_full_file() (64M). */
+#define READ_FULL_BYTES_MAX (64U*1024U*1024U - 1U)
+
+/* The maximum size of virtual files we'll read in one go in read_virtual_file() (4M). Note that this limit
+ * is different (and much lower) than the READ_FULL_BYTES_MAX limit. This reflects the fact that we use
+ * different strategies for reading virtual and regular files: virtual files are generally size constrained:
+ * there we allocate the full buffer size in advance. Regular files OTOH can be much larger, and here we grow
+ * the allocations exponentially in a loop. In glibc large allocations are immediately backed by mmap()
+ * making them relatively slow (measurably so). Thus, when allocating the full buffer in advance the large
+ * limit is a problem. When allocating piecemeal it's not. Hence pick two distinct limits. */
+#define READ_VIRTUAL_BYTES_MAX (4U*1024U*1024U - 1U)
int fopen_unlocked(const char *path, const char *options, FILE **ret) {
assert(ret);
@@ -392,7 +401,7 @@ int read_virtual_file(const char *filename, size_t max_size, char **ret_contents
if (fd < 0)
return -errno;
- assert(max_size <= READ_FULL_BYTES_MAX || max_size == SIZE_MAX);
+ assert(max_size <= READ_VIRTUAL_BYTES_MAX || max_size == SIZE_MAX);
/* Limit the number of attempts to read the number of bytes returned by fstat(). */
n_retries = 3;
@@ -407,7 +416,7 @@ int read_virtual_file(const char *filename, size_t max_size, char **ret_contents
return -EBADF;
/* Be prepared for files from /proc which generally report a file size of 0. */
- assert_cc(READ_FULL_BYTES_MAX < SSIZE_MAX);
+ assert_cc(READ_VIRTUAL_BYTES_MAX < SSIZE_MAX);
if (st.st_size > 0 && n_retries > 1) {
/* Let's use the file size if we have more than 1 attempt left. On the last attempt
* we'll ignore the file size */
@@ -421,13 +430,13 @@ int read_virtual_file(const char *filename, size_t max_size, char **ret_contents
} else {
size = MIN((size_t) st.st_size, max_size);
- if (size > READ_FULL_BYTES_MAX)
+ if (size > READ_VIRTUAL_BYTES_MAX)
return -EFBIG;
}
n_retries--;
} else {
- size = MIN(READ_FULL_BYTES_MAX, max_size);
+ size = MIN(READ_VIRTUAL_BYTES_MAX, max_size);
n_retries = 0;
}
@@ -436,7 +445,7 @@ int read_virtual_file(const char *filename, size_t max_size, char **ret_contents
return -ENOMEM;
/* Use a bigger allocation if we got it anyway, but not more than the limit. */
- size = MIN3(MALLOC_SIZEOF_SAFE(buf) - 1, max_size, READ_FULL_BYTES_MAX);
+ size = MIN3(MALLOC_SIZEOF_SAFE(buf) - 1, max_size, READ_VIRTUAL_BYTES_MAX);
for (;;) {
ssize_t k;
@@ -576,7 +585,7 @@ int read_full_stream_full(
}
memcpy_safe(t, buf, n);
explicit_bzero_safe(buf, n);
- buf = mfree(buf);
+ free(buf);
} else {
t = realloc(buf, n_next + 1);
if (!t)
diff --git a/src/libnm-systemd-shared/src/basic/fs-util.c b/src/libnm-systemd-shared/src/basic/fs-util.c
index ee8eec90bc..6545de76be 100644
--- a/src/libnm-systemd-shared/src/basic/fs-util.c
+++ b/src/libnm-systemd-shared/src/basic/fs-util.c
@@ -744,7 +744,7 @@ int inotify_add_watch_and_warn(int fd, const char *pathname, uint32_t mask) {
return wd;
}
-static bool unsafe_transition(const struct stat *a, const struct stat *b) {
+bool unsafe_transition(const struct stat *a, const struct stat *b) {
/* Returns true if the transition from a to b is safe, i.e. that we never transition from unprivileged to
* privileged files or directories. Why bother? So that unprivileged code can't symlink to privileged files
* making us believe we read something safe even though it isn't safe in the specific context we open it in. */
diff --git a/src/libnm-systemd-shared/src/basic/fs-util.h b/src/libnm-systemd-shared/src/basic/fs-util.h
index 7bac25704f..85bdea64df 100644
--- a/src/libnm-systemd-shared/src/basic/fs-util.h
+++ b/src/libnm-systemd-shared/src/basic/fs-util.h
@@ -94,6 +94,8 @@ enum {
CHASE_WARN = 1 << 7, /* Emit an appropriate warning when an error is encountered */
};
+bool unsafe_transition(const struct stat *a, const struct stat *b);
+
/* How many iterations to execute before returning -ELOOP */
#define CHASE_SYMLINKS_MAX 32
diff --git a/src/libnm-systemd-shared/src/basic/hexdecoct.c b/src/libnm-systemd-shared/src/basic/hexdecoct.c
index 6eb9343f21..3477c2fbf4 100644
--- a/src/libnm-systemd-shared/src/basic/hexdecoct.c
+++ b/src/libnm-systemd-shared/src/basic/hexdecoct.c
@@ -530,6 +530,16 @@ char base64char(int x) {
}
#endif /* NM_IGNORED */
+/* This is almost base64char(), but not entirely, as it uses the "url and filename safe" alphabet,
+ * since we don't want "/" appear in interface names (since interfaces appear in sysfs as filenames).
+ * See section #5 of RFC 4648. */
+char urlsafe_base64char(int x) {
+ static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789-_";
+ return table[x & 63];
+}
+
int unbase64char(char c) {
unsigned offset;
diff --git a/src/libnm-systemd-shared/src/basic/hexdecoct.h b/src/libnm-systemd-shared/src/basic/hexdecoct.h
index 7e2a6892c0..4ace5b7a99 100644
--- a/src/libnm-systemd-shared/src/basic/hexdecoct.h
+++ b/src/libnm-systemd-shared/src/basic/hexdecoct.h
@@ -27,6 +27,7 @@ char base32hexchar(int x) _const_;
int unbase32hexchar(char c) _const_;
char base64char(int x) _const_;
+char urlsafe_base64char(int x) _const_;
int unbase64char(char c) _const_;
char *base32hexmem(const void *p, size_t l, bool padding);
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 18c44cf178..cfcfa82aed 100644
--- a/src/libnm-systemd-shared/src/basic/in-addr-util.c
+++ b/src/libnm-systemd-shared/src/basic/in-addr-util.c
@@ -123,6 +123,12 @@ int in_addr_is_localhost(int family, const union in_addr_union *u) {
return -EAFNOSUPPORT;
}
+bool in6_addr_is_ipv4_mapped_address(const struct in6_addr *a) {
+ return a->s6_addr32[0] == 0 &&
+ a->s6_addr32[1] == 0 &&
+ a->s6_addr32[2] == htobe32(UINT32_C(0x0000ffff));
+}
+
bool in4_addr_equal(const struct in_addr *a, const struct in_addr *b) {
assert(a);
assert(b);
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 906b3fe97e..f3ead91962 100644
--- a/src/libnm-systemd-shared/src/basic/in-addr-util.h
+++ b/src/libnm-systemd-shared/src/basic/in-addr-util.h
@@ -58,6 +58,7 @@ int in_addr_is_localhost(int family, const union in_addr_union *u);
bool in4_addr_is_local_multicast(const struct in_addr *a);
bool in4_addr_is_non_local(const struct in_addr *a);
+bool in6_addr_is_ipv4_mapped_address(const struct in6_addr *a);
bool in4_addr_equal(const struct in_addr *a, const struct in_addr *b);
bool in6_addr_equal(const struct in6_addr *a, const struct in6_addr *b);
diff --git a/src/libnm-systemd-shared/src/basic/path-util.c b/src/libnm-systemd-shared/src/basic/path-util.c
index 55e4d31769..4e462b5832 100644
--- a/src/libnm-systemd-shared/src/basic/path-util.c
+++ b/src/libnm-systemd-shared/src/basic/path-util.c
@@ -722,7 +722,7 @@ int find_executable_full(const char *name, bool use_path_envvar, char **ret_file
}
bool paths_check_timestamp(const char* const* paths, usec_t *timestamp, bool update) {
- bool changed = false;
+ bool changed = false, originally_unset;
const char* const* i;
assert(timestamp);
@@ -730,6 +730,8 @@ bool paths_check_timestamp(const char* const* paths, usec_t *timestamp, bool upd
if (!paths)
return false;
+ originally_unset = *timestamp == 0;
+
STRV_FOREACH(i, paths) {
struct stat stats;
usec_t u;
@@ -739,11 +741,11 @@ bool paths_check_timestamp(const char* const* paths, usec_t *timestamp, bool upd
u = timespec_load(&stats.st_mtim);
- /* first check */
+ /* check first */
if (*timestamp >= u)
continue;
- log_debug("timestamp of '%s' changed", *i);
+ log_debug(originally_unset ? "Loaded timestamp for '%s'." : "Timestamp of '%s' changed.", *i);
/* update timestamp */
if (update) {
diff --git a/src/libnm-systemd-shared/src/basic/process-util.c b/src/libnm-systemd-shared/src/basic/process-util.c
index d538dda7a8..053819a956 100644
--- a/src/libnm-systemd-shared/src/basic/process-util.c
+++ b/src/libnm-systemd-shared/src/basic/process-util.c
@@ -826,7 +826,7 @@ int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout) {
/* Assuming we woke due to the child exiting. */
if (waitid(P_PID, pid, &status, WEXITED|WNOHANG) == 0) {
if (status.si_pid == pid) {
- /* This is the correct child.*/
+ /* This is the correct child. */
if (status.si_code == CLD_EXITED)
return (status.si_status == 0) ? 0 : -EPROTO;
else
diff --git a/src/libnm-systemd-shared/src/basic/random-util.c b/src/libnm-systemd-shared/src/basic/random-util.c
index 4af1fff567..063784dc83 100644
--- a/src/libnm-systemd-shared/src/basic/random-util.c
+++ b/src/libnm-systemd-shared/src/basic/random-util.c
@@ -190,7 +190,7 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
* invocations or so. That's because we don't really care about the quality here. We
* generally prefer using RDRAND if the caller allows us to, since this way we won't upset
* the kernel's random subsystem by accessing it before the pool is initialized (after all it
- * will kmsg log about every attempt to do so)..*/
+ * will kmsg log about every attempt to do so). */
for (;;) {
unsigned long u;
size_t m;
diff --git a/src/libnm-systemd-shared/src/basic/socket-util.c b/src/libnm-systemd-shared/src/basic/socket-util.c
index da36c2806c..02a776156e 100644
--- a/src/libnm-systemd-shared/src/basic/socket-util.c
+++ b/src/libnm-systemd-shared/src/basic/socket-util.c
@@ -112,7 +112,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) {
/* If there's no embedded NUL byte, then the size needs to match the whole
* structure or the structure with one extra NUL byte suffixed. (Yeah, Linux is awful,
* and considers both equivalent: getsockname() even extends sockaddr_un beyond its
- * size if the path is non NUL terminated.)*/
+ * size if the path is non NUL terminated.) */
if (!IN_SET(a->size, sizeof(a->sockaddr.un.sun_path), sizeof(a->sockaddr.un.sun_path)+1))
return -EINVAL;
}
@@ -1204,7 +1204,7 @@ int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path) {
/* Don't allow paths larger than the space in sockaddr_un. Note that we are a tiny bit more restrictive than
* the kernel is: we insist on NUL termination (both for abstract namespace and regular file system socket
* addresses!), which the kernel doesn't. We do this to reduce chance of incompatibility with other apps that
- * do not expect non-NUL terminated file system path*/
+ * do not expect non-NUL terminated file system path. */
if (l+1 > sizeof(ret->sun_path))
return -EINVAL;
diff --git a/src/libnm-systemd-shared/src/basic/time-util.c b/src/libnm-systemd-shared/src/basic/time-util.c
index 4b7042f78d..3d8299b3f0 100644
--- a/src/libnm-systemd-shared/src/basic/time-util.c
+++ b/src/libnm-systemd-shared/src/basic/time-util.c
@@ -1035,7 +1035,7 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
s = extract_multiplier(p + strspn(p, WHITESPACE), &multiplier);
if (s == p && *s != '\0')
- /* Don't allow '12.34.56', but accept '12.34 .56' or '12.34s.56'*/
+ /* Don't allow '12.34.56', but accept '12.34 .56' or '12.34s.56' */
return -EINVAL;
p = s;
@@ -1063,7 +1063,7 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
r += k;
}
- /* Don't allow "0.-0", "3.+1", "3. 1", "3.sec" or "3.hoge"*/
+ /* Don't allow "0.-0", "3.+1", "3. 1", "3.sec" or "3.hoge" */
if (b == e + 1)
return -EINVAL;
}
@@ -1210,7 +1210,7 @@ int parse_nsec(const char *t, nsec_t *nsec) {
s = extract_nsec_multiplier(p + strspn(p, WHITESPACE), &multiplier);
if (s == p && *s != '\0')
- /* Don't allow '12.34.56', but accept '12.34 .56' or '12.34s.56'*/
+ /* Don't allow '12.34.56', but accept '12.34 .56' or '12.34s.56' */
return -EINVAL;
p = s;
@@ -1238,7 +1238,7 @@ int parse_nsec(const char *t, nsec_t *nsec) {
r += k;
}
- /* Don't allow "0.-0", "3.+1", "3. 1", "3.sec" or "3.hoge"*/
+ /* Don't allow "0.-0", "3.+1", "3. 1", "3.sec" or "3.hoge" */
if (b == e + 1)
return -EINVAL;
}
@@ -1445,7 +1445,7 @@ int get_timezone(char **ret) {
r = readlink_malloc("/etc/localtime", &t);
if (r == -ENOENT) {
- /* If the symlink does not exist, assume "UTC", like glibc does*/
+ /* If the symlink does not exist, assume "UTC", like glibc does */
z = strdup("UTC");
if (!z)
return -ENOMEM;
diff --git a/src/libnm-systemd-shared/src/fundamental/string-util-fundamental.c b/src/libnm-systemd-shared/src/fundamental/string-util-fundamental.c
index c1abae6c41..f170392603 100644
--- a/src/libnm-systemd-shared/src/fundamental/string-util-fundamental.c
+++ b/src/libnm-systemd-shared/src/fundamental/string-util-fundamental.c
@@ -79,6 +79,7 @@ sd_char* endswith_no_case(const sd_char *s, const sd_char *postfix) {
return (sd_char*) s + sl - pl;
}
+#if 0 /* NM_IGNORED */
#ifdef SD_BOOT
static sd_bool isdigit(sd_char a) {
return a >= '0' && a <= '9';
@@ -154,7 +155,7 @@ sd_int strverscmp_improved(const sd_char *a, const sd_char *b) {
* Note that except for '~' prefixed segments, a string has more segments is newer.
* So, this check must be after the '~' check. */
if (*a == '\0' || *b == '\0')
- return strcmp(a, b);
+ return CMP(*a, *b);
/* Handle '-', which separates version and release, e.g 123.4-3.1.fc33.x86_64 */
if (*a == '-' || *b == '-') {
@@ -196,9 +197,9 @@ sd_int strverscmp_improved(const sd_char *a, const sd_char *b) {
/* Find the leading numeric segments. One may be an empty string. So,
* numeric segments are always newer than alpha segments. */
- for (aa = a; *aa != '\0' && isdigit(*aa); aa++)
+ for (aa = a; isdigit(*aa); aa++)
;
- for (bb = b; *bb != '\0' && isdigit(*bb); bb++)
+ for (bb = b; isdigit(*bb); bb++)
;
/* To compare numeric segments without parsing their values, first compare the
@@ -213,9 +214,9 @@ sd_int strverscmp_improved(const sd_char *a, const sd_char *b) {
return r;
} else {
/* Find the leading non-numeric segments. */
- for (aa = a; *aa != '\0' && is_alpha(*aa); aa++)
+ for (aa = a; is_alpha(*aa); aa++)
;
- for (bb = b; *bb != '\0' && is_alpha(*bb); bb++)
+ for (bb = b; is_alpha(*bb); bb++)
;
/* Note that the segments are usually not NUL-terminated. */
@@ -234,3 +235,4 @@ sd_int strverscmp_improved(const sd_char *a, const sd_char *b) {
b = bb;
}
}
+#endif /* NM_IGNORED */