diff options
author | Thomas Haller <thaller@redhat.com> | 2021-06-17 16:48:12 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2021-06-23 13:47:39 +0200 |
commit | fbf39522741bb5ffb8bdaef991486e3eb942f1a2 (patch) | |
tree | 8042706a18e0f00612ded50e2f428bd2a72d79d6 | |
parent | acd1a54d8f14680fc3bcd79f7fff55e6700d1d10 (diff) | |
parent | 02a4e00d562e8e73d7ede7644009e4327617b1c2 (diff) |
systemd: merge branch systemd into main
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/897
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 */ |