diff options
| author | Michael Biebl <biebl@debian.org> | 2025-02-12 13:46:50 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2025-02-12 13:46:50 +0100 |
| commit | 8bdf070ff046f482f6eb5e2b15ebc216f5d1e3da (patch) | |
| tree | f706478d189d54c6532e8863d4b0d5ff5575af60 /src/libnm-systemd-core | |
| parent | 818258cf34b83fbc754633295e1052d4752d7b15 (diff) | |
New upstream version 1.51.90 upstream/1.51.90
Diffstat (limited to 'src/libnm-systemd-core')
28 files changed, 599 insertions, 341 deletions
diff --git a/src/libnm-systemd-core/nm-sd.c b/src/libnm-systemd-core/nm-sd.c index b512e3fc..aecbdf94 100644 --- a/src/libnm-systemd-core/nm-sd.c +++ b/src/libnm-systemd-core/nm-sd.c @@ -70,7 +70,7 @@ event_create_source(sd_event *event) source->event = is_default_event ? g_steal_pointer(&event) : sd_event_ref(event); - source->pollfd = (GPollFD){ + source->pollfd = (GPollFD) { .fd = sd_event_get_fd(source->event), .events = G_IO_IN | G_IO_HUP | G_IO_ERR, }; diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp-duid-internal.h b/src/libnm-systemd-core/src/libsystemd-network/dhcp-duid-internal.h index f8bc15c4..0d3d6b5c 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/dhcp-duid-internal.h +++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp-duid-internal.h @@ -73,7 +73,7 @@ static inline bool duid_data_size_is_valid(size_t size) { return size >= MIN_DUID_DATA_LEN && size <= MAX_DUID_DATA_LEN; } -const char *duid_type_to_string(DUIDType t) _const_; +const char* duid_type_to_string(DUIDType t) _const_; int dhcp_duid_to_string_internal(uint16_t type, const void *data, size_t data_size, char **ret); int dhcp_identifier_set_iaid( 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 3fbfc028..ecd62ea8 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-internal.h +++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-internal.h @@ -84,9 +84,8 @@ struct sd_dhcp6_client { bool send_release; }; -int dhcp6_network_bind_udp_socket(int ifindex, struct in6_addr *address); -int dhcp6_network_send_udp_socket(int s, struct in6_addr *address, - const void *packet, size_t len); +int dhcp6_network_bind_udp_socket(int ifindex, const struct in6_addr *address); +int dhcp6_network_send_udp_socket(int s, const struct in6_addr *address, const void *packet, size_t len); int dhcp6_client_send_message(sd_dhcp6_client *client); int dhcp6_client_set_transaction_id(sd_dhcp6_client *client, uint32_t transaction_id); diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-lease-internal.h b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-lease-internal.h index e76a108f..60cd84f2 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-lease-internal.h +++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-lease-internal.h @@ -8,6 +8,7 @@ #include <inttypes.h> #include "sd-dhcp6-lease.h" +#include "dns-resolver-internal.h" #include "dhcp6-option.h" #include "dhcp6-protocol.h" @@ -38,6 +39,8 @@ struct sd_dhcp6_lease { struct in6_addr *dns; size_t dns_count; + sd_dns_resolver *dnr; + size_t n_dnr; char **domains; struct in6_addr *ntp; size_t ntp_count; diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-network.c b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-network.c index 7b17dbc1..03732692 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-network.c +++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-network.c @@ -19,9 +19,10 @@ #include "fd-util.h" #include "socket-util.h" -int dhcp6_network_bind_udp_socket(int ifindex, struct in6_addr *local_address) { +int dhcp6_network_bind_udp_socket(int ifindex, const struct in6_addr *local_address) { union sockaddr_union src = { .in6.sin6_family = AF_INET6, + .in6.sin6_addr = *ASSERT_PTR(local_address), .in6.sin6_port = htobe16(DHCP6_PORT_CLIENT), .in6.sin6_scope_id = ifindex, }; @@ -29,9 +30,6 @@ int dhcp6_network_bind_udp_socket(int ifindex, struct in6_addr *local_address) { int r; assert(ifindex > 0); - assert(local_address); - - src.in6.sin6_addr = *local_address; s = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_UDP); if (s < 0) @@ -60,20 +58,14 @@ int dhcp6_network_bind_udp_socket(int ifindex, struct in6_addr *local_address) { return TAKE_FD(s); } -int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address, - const void *packet, size_t len) { +int dhcp6_network_send_udp_socket(int s, const struct in6_addr *server_address, const void *packet, size_t len) { union sockaddr_union dest = { .in6.sin6_family = AF_INET6, + .in6.sin6_addr = *ASSERT_PTR(server_address), .in6.sin6_port = htobe16(DHCP6_PORT_SERVER), }; - int r; - - assert(server_address); - memcpy(&dest.in6.sin6_addr, server_address, sizeof(dest.in6.sin6_addr)); - - r = sendto(s, packet, len, 0, &dest.sa, sizeof(dest.in6)); - if (r < 0) + if (sendto(s, packet, len, 0, &dest.sa, sizeof(dest.in6)) < 0) return -errno; return 0; 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 5fa9b265..4e30c9e5 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.c +++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.c @@ -208,6 +208,7 @@ bool dhcp6_option_can_request(uint16_t option) { case SD_DHCP6_OPTION_V6_DOTS_RI: case SD_DHCP6_OPTION_V6_DOTS_ADDRESS: case SD_DHCP6_OPTION_IPV6_ADDRESS_ANDSF: + case SD_DHCP6_OPTION_V6_DNR: return true; default: return false; @@ -822,74 +823,6 @@ int dhcp6_option_parse_addresses( return 0; } -static int parse_domain(const uint8_t **data, size_t *len, char **ret) { - _cleanup_free_ char *domain = NULL; - const uint8_t *optval; - size_t optlen, n = 0; - int r; - - assert(data); - assert(len); - assert(*data || *len == 0); - assert(ret); - - optval = *data; - optlen = *len; - - if (optlen <= 1) - return -ENODATA; - - for (;;) { - const char *label; - uint8_t c; - - if (optlen == 0) - break; - - c = *optval; - optval++; - optlen--; - - if (c == 0) - /* End label */ - break; - if (c > 63) - return -EBADMSG; - if (c > optlen) - return -EMSGSIZE; - - /* Literal label */ - label = (const char*) optval; - optval += c; - optlen -= c; - - if (!GREEDY_REALLOC(domain, n + (n != 0) + DNS_LABEL_ESCAPED_MAX)) - return -ENOMEM; - - if (n != 0) - domain[n++] = '.'; - - r = dns_label_escape(label, c, domain + n, DNS_LABEL_ESCAPED_MAX); - if (r < 0) - return r; - - n += r; - } - - if (n > 0) { - if (!GREEDY_REALLOC(domain, n + 1)) - return -ENOMEM; - - domain[n] = '\0'; - } - - *ret = TAKE_PTR(domain); - *data = optval; - *len = optlen; - - return n; -} - int dhcp6_option_parse_domainname(const uint8_t *optval, size_t optlen, char **ret) { _cleanup_free_ char *domain = NULL; int r; @@ -897,7 +830,7 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, size_t optlen, char **r assert(optval || optlen == 0); assert(ret); - r = parse_domain(&optval, &optlen, &domain); + r = dns_name_from_wire_format(&optval, &optlen, &domain); if (r < 0) return r; if (r == 0) @@ -924,11 +857,11 @@ int dhcp6_option_parse_domainname_list(const uint8_t *optval, size_t optlen, cha while (optlen > 0) { _cleanup_free_ char *name = NULL; - r = parse_domain(&optval, &optlen, &name); + r = dns_name_from_wire_format(&optval, &optlen, &name); if (r < 0) return r; - if (r == 0) - continue; + if (dns_name_is_root(name)) /* root domain */ + return -EBADMSG; r = strv_consume(&names, TAKE_PTR(name)); if (r < 0) diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-protocol.h b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-protocol.h index c70f9320..39f5040f 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-protocol.h +++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-protocol.h @@ -28,9 +28,11 @@ typedef struct DHCP6Message DHCP6Message; #define DHCP6_MIN_OPTIONS_SIZE \ 1280 - sizeof(struct ip6_hdr) - sizeof(struct udphdr) -#define IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT \ - { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02 } } } +#define IN6_ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS \ + ((const struct in6_addr) { { { \ + 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, \ + } } } ) enum { DHCP6_PORT_SERVER = 547, @@ -150,9 +152,9 @@ typedef enum DHCP6FQDNFlag { DHCP6_FQDN_FLAG_N = 1 << 2, } DHCP6FQDNFlag; -const char *dhcp6_state_to_string(DHCP6State s) _const_; -const char *dhcp6_message_type_to_string(DHCP6MessageType s) _const_; +const char* dhcp6_state_to_string(DHCP6State s) _const_; +const char* dhcp6_message_type_to_string(DHCP6MessageType s) _const_; DHCP6MessageType dhcp6_message_type_from_string(const char *s) _pure_; -const char *dhcp6_message_status_to_string(DHCP6Status s) _const_; +const char* dhcp6_message_status_to_string(DHCP6Status s) _const_; DHCP6Status dhcp6_message_status_from_string(const char *s) _pure_; int dhcp6_message_status_to_errno(DHCP6Status s); diff --git a/src/libnm-systemd-core/src/libsystemd-network/network-common.c b/src/libnm-systemd-core/src/libsystemd-network/network-common.c index 8d62e6ff..f61b11f5 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/network-common.c +++ b/src/libnm-systemd-core/src/libsystemd-network/network-common.c @@ -3,7 +3,7 @@ #include "nm-sd-adapt-core.h" #include "env-util.h" -#include "format-util.h" +#include "format-ifname.h" #include "network-common.h" #include "socket-util.h" #include "unaligned.h" 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 a6b55d07..5655c0d7 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 @@ -749,8 +749,6 @@ static int client_append_mudurl(sd_dhcp6_client *client, uint8_t **buf, size_t * int dhcp6_client_send_message(sd_dhcp6_client *client) { _cleanup_free_ uint8_t *buf = NULL; - struct in6_addr all_servers = - IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT; struct sd_dhcp6_option *j; usec_t elapsed_usec, time_now; be16_t elapsed_time; @@ -845,7 +843,7 @@ int dhcp6_client_send_message(sd_dhcp6_client *client) { if (r < 0) return r; - r = dhcp6_network_send_udp_socket(client->fd, &all_servers, buf, offset); + r = dhcp6_network_send_udp_socket(client->fd, &IN6_ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS, buf, offset); if (r < 0) return r; @@ -1336,7 +1334,7 @@ static int client_receive_message( return 0; } if ((size_t) len < sizeof(DHCP6Message)) { - log_dhcp6_client(client, "Too small to be DHCP6 message: ignoring"); + log_dhcp6_client(client, "Too small to be DHCPv6 message: ignoring"); return 0; } @@ -1412,7 +1410,7 @@ int sd_dhcp6_client_stop(sd_dhcp6_client *client) { r = client_send_release(client); if (r < 0) log_dhcp6_client_errno(client, r, - "Failed to send DHCP6 release message, ignoring: %m"); + "Failed to send DHCPv6 release message, ignoring: %m"); client_stop(client, SD_DHCP6_CLIENT_EVENT_STOP); @@ -1423,7 +1421,8 @@ int sd_dhcp6_client_stop(sd_dhcp6_client *client) { } int sd_dhcp6_client_is_running(sd_dhcp6_client *client) { - assert_return(client, -EINVAL); + if (!client) + return false; return client->state != DHCP6_STATE_STOPPED; } 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 a42df243..9569af58 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 @@ -10,7 +10,9 @@ #include "alloc-util.h" #include "dhcp6-internal.h" #include "dhcp6-lease-internal.h" +#include "dns-domain.h" #include "network-common.h" +#include "sort-util.h" #include "strv.h" #include "unaligned.h" @@ -426,7 +428,7 @@ int dhcp6_lease_add_domains(sd_dhcp6_lease *lease, const uint8_t *optval, size_t if (r < 0) return r; - return strv_extend_strv(&lease->domains, domains, true); + return strv_extend_strv_consume(&lease->domains, TAKE_PTR(domains), /* filter_duplicates = */ true); } int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***ret) { @@ -440,6 +442,105 @@ int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***ret) { return strv_length(lease->domains); } +#if 0 /* NM_IGNORED */ +static int dhcp6_lease_add_dnr(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen) { + int r; + + assert(lease); + + _cleanup_(sd_dns_resolver_done) sd_dns_resolver res = {}; + + size_t offset = 0; + + /* priority */ + if (optlen - offset < sizeof(uint16_t)) + return -EBADMSG; + res.priority = unaligned_read_be16(optval + offset); + offset += sizeof(uint16_t); + + /* adn */ + if (optlen - offset < sizeof(uint16_t)) + return -EBADMSG; + size_t ilen = unaligned_read_be16(optval + offset); + offset += sizeof(uint16_t); + if (offset + ilen > optlen) + return -EBADMSG; + + r = dhcp6_option_parse_domainname(optval + offset, ilen, &res.auth_name); + if (r < 0) + return r; + r = dns_name_is_valid_ldh(res.auth_name); + if (r < 0) + return r; + if (!r) + return -EBADMSG; + offset += ilen; + + /* RFC9463 § 3.1.6: adn only mode */ + if (offset == optlen) + return 0; + + /* addrs */ + if (optlen - offset < sizeof(uint16_t)) + return -EBADMSG; + ilen = unaligned_read_be16(optval + offset); + offset += sizeof(uint16_t); + if (offset + ilen > optlen) + return -EBADMSG; + + _cleanup_free_ struct in6_addr *addrs = NULL; + size_t n_addrs = 0; + + r = dhcp6_option_parse_addresses(optval + offset, ilen, &addrs, &n_addrs); + if (r < 0) + return r; + if (n_addrs == 0) + return -EBADMSG; + offset += ilen; + + res.addrs = new(union in_addr_union, n_addrs); + if (!res.addrs) + return -ENOMEM; + + for (size_t i = 0; i < n_addrs; i++) { + union in_addr_union addr = {.in6 = addrs[i]}; + /* RFC9463 § 6.2 client MUST discard multicast and host loopback addresses */ + if (in_addr_is_multicast(AF_INET6, &addr) || + in_addr_is_localhost(AF_INET6, &addr)) + return -EBADMSG; + res.addrs[i] = addr; + } + res.n_addrs = n_addrs; + res.family = AF_INET6; + + /* svc params */ + r = dnr_parse_svc_params(optval + offset, optlen-offset, &res); + if (r < 0) + return r; + + /* Append this resolver */ + if (!GREEDY_REALLOC(lease->dnr, lease->n_dnr+1)) + return -ENOMEM; + + lease->dnr[lease->n_dnr++] = TAKE_STRUCT(res); + + typesafe_qsort(lease->dnr, lease->n_dnr, dns_resolver_prio_compare); + + return 1; +} + +int sd_dhcp6_lease_get_dnr(sd_dhcp6_lease *lease, sd_dns_resolver **ret) { + assert_return(lease, -EINVAL); + assert_return(ret, -EINVAL); + + if (!lease->dnr) + return -ENODATA; + + *ret = lease->dnr; + return lease->n_dnr; +} +#endif /* NM_IGNORED */ + int dhcp6_lease_add_ntp(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen) { int r; @@ -765,8 +866,7 @@ static int dhcp6_lease_parse_message( continue; } - dhcp6_ia_free(lease->ia_na); - lease->ia_na = TAKE_PTR(ia); + free_and_replace_full(lease->ia_na, ia, dhcp6_ia_free); break; } case SD_DHCP6_OPTION_IA_PD: { @@ -790,8 +890,7 @@ static int dhcp6_lease_parse_message( continue; } - dhcp6_ia_free(lease->ia_pd); - lease->ia_pd = TAKE_PTR(ia); + free_and_replace_full(lease->ia_pd, ia, dhcp6_ia_free); break; } case SD_DHCP6_OPTION_RAPID_COMMIT: @@ -852,7 +951,16 @@ static int dhcp6_lease_parse_message( irt = unaligned_be32_sec_to_usec(optval, /* max_as_infinity = */ false); break; +#if 0 /* NM_IGNORED */ + case SD_DHCP6_OPTION_V6_DNR: + r = dhcp6_lease_add_dnr(lease, optval, optlen); + if (r < 0) + return log_dhcp6_client_errno(client, r, "Failed to parse DNR option, ignoring: %m"); + if (r == 0) + log_dhcp6_client(client, "Received ADN-only DNRv6 option, ignoring."); + break; +#endif /* NM_IGNORED */ case SD_DHCP6_OPTION_VENDOR_OPTS: r = dhcp6_lease_add_vendor_option(lease, optval, optlen); if (r < 0) @@ -906,6 +1014,9 @@ static sd_dhcp6_lease *dhcp6_lease_free(sd_dhcp6_lease *lease) { dhcp6_ia_free(lease->ia_na); dhcp6_ia_free(lease->ia_pd); free(lease->dns); +#if 0 /* NM_IGNORED */ + dns_resolver_done_many(lease->dnr, lease->n_dnr); +#endif /* NM_IGNORED */ free(lease->fqdn); free(lease->captive_portal); strv_free(lease->domains); diff --git a/src/libnm-systemd-core/src/libsystemd/sd-device/device-private.c b/src/libnm-systemd-core/src/libsystemd/sd-device/device-private.c index eef3d618..6b17e772 100644 --- a/src/libnm-systemd-core/src/libsystemd/sd-device/device-private.c +++ b/src/libnm-systemd-core/src/libsystemd/sd-device/device-private.c @@ -714,7 +714,7 @@ static int device_tag(sd_device *device, const char *tag, bool add) { assert(device); assert(tag); - r = device_get_device_id(device, &id); + r = sd_device_get_device_id(device, &id); if (r < 0) return r; @@ -801,7 +801,7 @@ static int device_get_db_path(sd_device *device, char **ret) { assert(device); assert(ret); - r = device_get_device_id(device, &id); + r = sd_device_get_device_id(device, &id); if (r < 0) return r; diff --git a/src/libnm-systemd-core/src/libsystemd/sd-device/device-private.h b/src/libnm-systemd-core/src/libsystemd/sd-device/device-private.h index e1f3b6e8..eab54203 100644 --- a/src/libnm-systemd-core/src/libsystemd/sd-device/device-private.h +++ b/src/libnm-systemd-core/src/libsystemd/sd-device/device-private.h @@ -20,10 +20,12 @@ int device_opendir(sd_device *device, const char *subdir, DIR **ret); int device_get_property_bool(sd_device *device, const char *key); int device_get_property_int(sd_device *device, const char *key, int *ret); int device_get_sysattr_int(sd_device *device, const char *sysattr, int *ret_value); -int device_get_sysattr_unsigned(sd_device *device, const char *sysattr, unsigned *ret_value); +int device_get_sysattr_unsigned_full(sd_device *device, const char *sysattr, unsigned base, unsigned *ret_value); +static inline int device_get_sysattr_unsigned(sd_device *device, const char *sysattr, unsigned *ret_value) { + return device_get_sysattr_unsigned_full(device, sysattr, 0, ret_value); +} int device_get_sysattr_u32(sd_device *device, const char *sysattr, uint32_t *ret_value); int device_get_sysattr_bool(sd_device *device, const char *sysattr); -int device_get_device_id(sd_device *device, const char **ret); int device_get_devlink_priority(sd_device *device, int *ret); int device_get_devnode_mode(sd_device *device, mode_t *ret); int device_get_devnode_uid(sd_device *device, uid_t *ret); @@ -73,5 +75,5 @@ int device_read_uevent_file(sd_device *device); int device_set_action(sd_device *device, sd_device_action_t a); sd_device_action_t device_action_from_string(const char *s) _pure_; -const char *device_action_to_string(sd_device_action_t a) _const_; +const char* device_action_to_string(sd_device_action_t a) _const_; void dump_device_action_table(void); diff --git a/src/libnm-systemd-core/src/libsystemd/sd-device/device-util.h b/src/libnm-systemd-core/src/libsystemd/sd-device/device-util.h index 534a2967..b17993d5 100644 --- a/src/libnm-systemd-core/src/libsystemd/sd-device/device-util.h +++ b/src/libnm-systemd-core/src/libsystemd/sd-device/device-util.h @@ -100,7 +100,7 @@ static inline int devname_from_stat_rdev(const struct stat *st, char **ret) { assert(st); return devname_from_devnum(st->st_mode, st->st_rdev, ret); } -int device_open_from_devnum(mode_t mode, dev_t devnum, int flags, char **ret); +int device_open_from_devnum(mode_t mode, dev_t devnum, int flags, char **ret_devname); char** device_make_log_fields(sd_device *device); diff --git a/src/libnm-systemd-core/src/libsystemd/sd-device/sd-device.c b/src/libnm-systemd-core/src/libsystemd/sd-device/sd-device.c index 0ca87146..480223d0 100644 --- a/src/libnm-systemd-core/src/libsystemd/sd-device/sd-device.c +++ b/src/libnm-systemd-core/src/libsystemd/sd-device/sd-device.c @@ -243,7 +243,7 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) { r = path_simplify_alloc(_syspath, &syspath); if (r < 0) - return r; + return log_oom_debug(); } assert_se(devpath = startswith(syspath, "/sys")); @@ -354,9 +354,11 @@ _public_ int sd_device_new_from_ifname(sd_device **ret, const char *ifname) { assert_return(ret, -EINVAL); assert_return(ifname, -EINVAL); - r = device_new_from_main_ifname(ret, ifname); - if (r >= 0) - return r; + if (ifname_valid(ifname)) { + r = device_new_from_main_ifname(ret, ifname); + if (r >= 0) + return r; + } r = rtnl_resolve_ifname_full(NULL, RESOLVE_IFNAME_ALTERNATIVE | RESOLVE_IFNAME_NUMERIC, ifname, &main_name, NULL); if (r < 0) @@ -393,25 +395,79 @@ _public_ int sd_device_new_from_ifindex(sd_device **ret, int ifindex) { return 0; } -static int device_strjoin_new( +static int device_new_from_path_join( + sd_device **device, + const char *subsystem, + const char *driver_subsystem, + const char *sysname, const char *a, const char *b, const char *c, - const char *d, - sd_device **ret) { + const char *d) { - const char *p; + _cleanup_(sd_device_unrefp) sd_device *new_device = NULL; + _cleanup_free_ char *p = NULL; int r; - p = strjoina(a, b, c, d); - if (access(p, F_OK) < 0) - return IN_SET(errno, ENOENT, ENAMETOOLONG) ? 0 : -errno; /* If this sysfs is too long then it doesn't exist either */ + assert(device); + assert(sysname); + + p = path_join(a, b, c, d); + if (!p) + return -ENOMEM; + + r = sd_device_new_from_syspath(&new_device, p); + if (r == -ENODEV) + return 0; + if (r < 0) + return r; + + /* Check if the found device really has the expected subsystem and sysname, for safety. */ + if (!device_in_subsystem(new_device, subsystem)) + return 0; + + const char *new_driver_subsystem = NULL; + (void) sd_device_get_driver_subsystem(new_device, &new_driver_subsystem); + + if (!streq_ptr(driver_subsystem, new_driver_subsystem)) + return 0; + + const char *new_sysname; + r = sd_device_get_sysname(new_device, &new_sysname); + if (r < 0) + return r; + + if (!streq(sysname, new_sysname)) + return 0; + + /* If this is the first device we found, then take it. */ + if (!*device) { + *device = TAKE_PTR(new_device); + return 1; + } + + /* Unfortunately, (subsystem, sysname) pair is not unique. For examples, + * - /sys/bus/gpio and /sys/class/gpio, both have gpiochip%N. However, these point to different devpaths. + * - /sys/bus/mdio_bus and /sys/class/mdio_bus, + * - /sys/bus/mei and /sys/class/mei, + * - /sys/bus/typec and /sys/class/typec, and so on. + * Hence, if we already know a device, then we need to check if it is equivalent to the newly found one. */ + + const char *devpath, *new_devpath; + r = sd_device_get_devpath(*device, &devpath); + if (r < 0) + return r; - r = sd_device_new_from_syspath(ret, p); + r = sd_device_get_devpath(new_device, &new_devpath); if (r < 0) return r; - return 1; + if (!streq(devpath, new_devpath)) + return log_debug_errno(SYNTHETIC_ERRNO(ETOOMANYREFS), + "sd-device: found multiple devices for subsystem=%s and sysname=%s, refusing: %s, %s", + subsystem, sysname, devpath, new_devpath); + + return 1; /* Fortunately, they are consistent. */ } _public_ int sd_device_new_from_subsystem_sysname( @@ -419,6 +475,7 @@ _public_ int sd_device_new_from_subsystem_sysname( const char *subsystem, const char *sysname) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; char *name; int r; @@ -437,19 +494,15 @@ _public_ int sd_device_new_from_subsystem_sysname( if (streq(subsystem, "subsystem")) { FOREACH_STRING(s, "/sys/bus/", "/sys/class/") { - r = device_strjoin_new(s, name, NULL, NULL, ret); + r = device_new_from_path_join(&device, subsystem, /* driver_subsystem = */ NULL, sysname, s, name, NULL, NULL); if (r < 0) return r; - if (r > 0) - return 0; } } else if (streq(subsystem, "module")) { - r = device_strjoin_new("/sys/module/", name, NULL, NULL, ret); + r = device_new_from_path_join(&device, subsystem, /* driver_subsystem = */ NULL, sysname, "/sys/module/", name, NULL, NULL); if (r < 0) return r; - if (r > 0) - return 0; } else if (streq(subsystem, "drivers")) { const char *sep; @@ -461,35 +514,33 @@ _public_ int sd_device_new_from_subsystem_sysname( sep++; if (streq(sep, "drivers")) /* If the sysname is "drivers", then it's the drivers directory itself that is meant. */ - r = device_strjoin_new("/sys/bus/", subsys, "/drivers", NULL, ret); + r = device_new_from_path_join(&device, subsystem, subsys, "drivers", "/sys/bus/", subsys, "/drivers", NULL); else - r = device_strjoin_new("/sys/bus/", subsys, "/drivers/", sep, ret); + r = device_new_from_path_join(&device, subsystem, subsys, sep, "/sys/bus/", subsys, "/drivers/", sep); if (r < 0) return r; - if (r > 0) - return 0; } } - r = device_strjoin_new("/sys/bus/", subsystem, "/devices/", name, ret); + r = device_new_from_path_join(&device, subsystem, /* driver_subsystem = */ NULL, sysname, "/sys/bus/", subsystem, "/devices/", name); if (r < 0) return r; - if (r > 0) - return 0; - r = device_strjoin_new("/sys/class/", subsystem, "/", name, ret); + r = device_new_from_path_join(&device, subsystem, /* driver_subsystem = */ NULL, sysname, "/sys/class/", subsystem, name, NULL); if (r < 0) return r; - if (r > 0) - return 0; - r = device_strjoin_new("/sys/firmware/", subsystem, "/", name, ret); + /* Note that devices under /sys/firmware/ (e.g. /sys/firmware/devicetree/base/) do not have + * subsystem. Hence, pass NULL for subsystem. See issue #35861. */ + r = device_new_from_path_join(&device, /* subsystem = */ NULL, /* driver_subsystem = */ NULL, sysname, "/sys/firmware/", subsystem, name, NULL); if (r < 0) return r; - if (r > 0) - return 0; - return -ENODEV; + if (!device) + return -ENODEV; + + *ret = TAKE_PTR(device); + return 0; } _public_ int sd_device_new_from_stat_rdev(sd_device **ret, const struct stat *st) { @@ -499,10 +550,8 @@ _public_ int sd_device_new_from_stat_rdev(sd_device **ret, const struct stat *st return device_new_from_mode_and_devnum(ret, st->st_mode, st->st_rdev); } -_public_ int sd_device_new_from_devname(sd_device **ret, const char *devname) { - struct stat st; - dev_t devnum; - mode_t mode; +static int device_new_from_devname(sd_device **ret, const char *devname, bool strict) { + int r; assert_return(ret, -EINVAL); assert_return(devname, -EINVAL); @@ -510,28 +559,41 @@ _public_ int sd_device_new_from_devname(sd_device **ret, const char *devname) { /* This function actually accepts both devlinks and devnames, i.e. both symlinks and device * nodes below /dev/. */ - /* Also ignore when the specified path is "/dev". */ - if (isempty(path_startswith(devname, "/dev"))) + if (strict && isempty(path_startswith(devname, "/dev/"))) return -EINVAL; + dev_t devnum; + mode_t mode; if (device_path_parse_major_minor(devname, &mode, &devnum) >= 0) /* Let's shortcut when "/dev/block/maj:min" or "/dev/char/maj:min" is specified. * In that case, we can directly convert the path to syspath, hence it is not necessary * that the specified path exists. So, this works fine without udevd being running. */ return device_new_from_mode_and_devnum(ret, mode, devnum); - if (stat(devname, &st) < 0) - return ERRNO_IS_DEVICE_ABSENT(errno) ? -ENODEV : -errno; + _cleanup_free_ char *resolved = NULL; + struct stat st; + r = chase_and_stat(devname, /* root = */ NULL, /* flags = */ 0, &resolved, &st); + if (ERRNO_IS_NEG_DEVICE_ABSENT(r)) + return -ENODEV; + if (r < 0) + return r; + + if (isempty(path_startswith(resolved, "/dev/"))) + return -EINVAL; return sd_device_new_from_stat_rdev(ret, &st); } +_public_ int sd_device_new_from_devname(sd_device **ret, const char *devname) { + return device_new_from_devname(ret, devname, /* strict = */ true); +} + _public_ int sd_device_new_from_path(sd_device **ret, const char *path) { assert_return(ret, -EINVAL); assert_return(path, -EINVAL); - if (path_startswith(path, "/dev")) - return sd_device_new_from_devname(ret, path); + if (device_new_from_devname(ret, path, /* strict = */ false) >= 0) + return 0; return device_new_from_syspath(ret, path, /* strict = */ false); } @@ -1211,6 +1273,20 @@ _public_ int sd_device_get_subsystem(sd_device *device, const char **ret) { } #if 0 /* NM_IGNORED */ +_public_ int sd_device_get_driver_subsystem(sd_device *device, const char **ret) { + assert_return(device, -EINVAL); + + if (!device_in_subsystem(device, "drivers")) + return -ENOENT; + + assert(device->driver_subsystem); + + if (ret) + *ret = device->driver_subsystem; + + return 0; +} + _public_ int sd_device_get_devtype(sd_device *device, const char **devtype) { int r; @@ -1226,7 +1302,7 @@ _public_ int sd_device_get_devtype(sd_device *device, const char **devtype) { if (devtype) *devtype = device->devtype; - return !!device->devtype; + return 0; } _public_ int sd_device_get_parent_with_subsystem_devtype(sd_device *device, const char *subsystem, const char *devtype, sd_device **ret) { @@ -1645,9 +1721,8 @@ static int handle_db_line(sd_device *device, char key, const char *value) { } } -int device_get_device_id(sd_device *device, const char **ret) { - assert(device); - assert(ret); +_public_ int sd_device_get_device_id(sd_device *device, const char **ret) { + assert_return(device, -EINVAL); if (!device->device_id) { _cleanup_free_ char *id = NULL; @@ -1697,7 +1772,8 @@ int device_get_device_id(sd_device *device, const char **ret) { device->device_id = TAKE_PTR(id); } - *ret = device->device_id; + if (ret) + *ret = device->device_id; return 0; } @@ -2428,7 +2504,7 @@ int device_get_sysattr_int(sd_device *device, const char *sysattr, int *ret_valu return v > 0; } -int device_get_sysattr_unsigned(sd_device *device, const char *sysattr, unsigned *ret_value) { +int device_get_sysattr_unsigned_full(sd_device *device, const char *sysattr, unsigned base, unsigned *ret_value) { const char *value; int r; @@ -2437,7 +2513,7 @@ int device_get_sysattr_unsigned(sd_device *device, const char *sysattr, unsigned return r; unsigned v; - r = safe_atou(value, &v); + r = safe_atou_full(value, base, &v); if (r < 0) return log_device_debug_errno(device, r, "Failed to parse '%s' attribute: %m", sysattr); diff --git a/src/libnm-systemd-core/src/libsystemd/sd-event/event-source.h b/src/libnm-systemd-core/src/libsystemd/sd-event/event-source.h index f4e38d78..d05bcf05 100644 --- a/src/libnm-systemd-core/src/libsystemd/sd-event/event-source.h +++ b/src/libnm-systemd-core/src/libsystemd/sd-event/event-source.h @@ -189,6 +189,9 @@ struct inode_data { * iteration. */ int fd; + /* The path that the fd points to. The field is optional. */ + char *path; + /* The inotify "watch descriptor" */ int wd; diff --git a/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.c b/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.c index ef0c2d2a..ac986e48 100644 --- a/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.c +++ b/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.c @@ -171,4 +171,13 @@ int event_add_child_pidref( return sd_event_add_child(e, s, pid->pid, options, callback, userdata); } + +dual_timestamp* event_dual_timestamp_now(sd_event *e, dual_timestamp *ts) { + assert(e); + assert(ts); + + assert_se(sd_event_now(e, CLOCK_REALTIME, &ts->realtime) >= 0); + assert_se(sd_event_now(e, CLOCK_MONOTONIC, &ts->monotonic) >= 0); + return ts; +} #endif /* NM_IGNORED */ diff --git a/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.h b/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.h index ad0f2e78..c0db014f 100644 --- a/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.h +++ b/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.h @@ -37,4 +37,6 @@ int event_add_time_change(sd_event *e, sd_event_source **ret, sd_event_io_handle #if 0 /* NM_IGNORED */ int event_add_child_pidref(sd_event *e, sd_event_source **s, const PidRef *pid, int options, sd_event_child_handler_t callback, void *userdata); + +dual_timestamp* event_dual_timestamp_now(sd_event *e, dual_timestamp *ts); #endif /* NM_IGNORED */ 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 6449b85c..b345b145 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 @@ -27,9 +27,11 @@ #include "missing_magic.h" #include "missing_syscall.h" #include "missing_threads.h" +#include "missing_wait.h" #include "origin-id.h" #include "path-util.h" #include "prioq.h" +#include "pidfd-util.h" #include "process-util.h" #include "psi-util.h" #include "set.h" @@ -184,7 +186,7 @@ static thread_local sd_event *default_event = NULL; static void source_disconnect(sd_event_source *s); static void event_gc_inode_data(sd_event *e, struct inode_data *d); -static sd_event *event_resolve(sd_event *e) { +static sd_event* event_resolve(sd_event *e) { return e == SD_EVENT_DEFAULT ? default_event : e; } @@ -340,7 +342,7 @@ static void free_clock_data(struct clock_data *d) { prioq_free(d->latest); } -static sd_event *event_free(sd_event *e) { +static sd_event* event_free(sd_event *e) { sd_event_source *s; assert(e); @@ -445,7 +447,7 @@ fail: } /* Define manually so we can add the origin check */ -_public_ sd_event *sd_event_ref(sd_event *e) { +_public_ sd_event* sd_event_ref(sd_event *e) { if (!e) return NULL; if (event_origin_changed(e)) @@ -473,8 +475,13 @@ _public_ sd_event* sd_event_unref(sd_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) - (void) sd_event_source_set_enabled(s, SD_EVENT_OFF); + int r; + + r = sd_event_source_set_enabled(s, SD_EVENT_OFF); + if (r < 0) + log_debug_errno(r, "Failed to disable event source %p (%s): %m", + s, strna(s->description)); + return sd_event_source_unref(s); } @@ -1072,6 +1079,8 @@ static void source_disconnect(sd_event_source *s) { } static sd_event_source* source_free(sd_event_source *s) { + int r; + assert(s); source_disconnect(s); @@ -1085,31 +1094,23 @@ static sd_event_source* source_free(sd_event_source *s) { if (s->child.process_owned) { if (!s->child.exited) { - bool sent = false; - - if (s->child.pidfd >= 0) { - if (pidfd_send_signal(s->child.pidfd, SIGKILL, NULL, 0) < 0) { - if (errno == ESRCH) /* Already dead */ - sent = true; - else if (!ERRNO_IS_NOT_SUPPORTED(errno)) - log_debug_errno(errno, "Failed to kill process " PID_FMT " via pidfd_send_signal(), re-trying via kill(): %m", - s->child.pid); - } else - sent = true; - } - - if (!sent) - if (kill(s->child.pid, SIGKILL) < 0) - if (errno != ESRCH) /* Already dead */ - log_debug_errno(errno, "Failed to kill process " PID_FMT " via kill(), ignoring: %m", - s->child.pid); + if (s->child.pidfd >= 0) + r = RET_NERRNO(pidfd_send_signal(s->child.pidfd, SIGKILL, NULL, 0)); + else + r = RET_NERRNO(kill(s->child.pid, SIGKILL)); + if (r < 0 && r != -ESRCH) + log_debug_errno(r, "Failed to kill process " PID_FMT ", ignoring: %m", + s->child.pid); } if (!s->child.waited) { siginfo_t si = {}; /* Reap the child if we can */ - (void) waitid(P_PID, s->child.pid, &si, WEXITED); + if (s->child.pidfd >= 0) + (void) waitid(P_PIDFD, s->child.pidfd, &si, WEXITED); + else + (void) waitid(P_PID, s->child.pid, &si, WEXITED); } } @@ -1179,7 +1180,7 @@ static int source_set_pending(sd_event_source *s, bool b) { return 1; } -static sd_event_source *source_new(sd_event *e, bool floating, EventSourceType type) { +static sd_event_source* source_new(sd_event *e, bool floating, EventSourceType type) { /* Let's allocate exactly what we need. Note that the difference of the smallest event source * structure to the largest is 144 bytes on x86-64 at the time of writing, i.e. more than two cache @@ -1577,11 +1578,6 @@ static int child_exit_callback(sd_event_source *s, const siginfo_t *si, void *us return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); } -static bool shall_use_pidfd(void) { - /* Mostly relevant for debugging, i.e. this is used in test-event.c to test the event loop once with and once without pidfd */ - return secure_getenv_bool("SYSTEMD_PIDFD") != 0; -} - _public_ int sd_event_add_child( sd_event *e, sd_event_source **ret, @@ -1629,34 +1625,29 @@ _public_ int sd_event_add_child( if (!s) return -ENOMEM; + /* We always take a pidfd here if we can, even if we wait for anything else than WEXITED, so that we + * pin the PID, and make regular waitid() handling race-free. */ + + s->child.pidfd = pidfd_open(pid, 0); + if (s->child.pidfd < 0) + return -errno; + + s->child.pidfd_owned = true; /* If we allocate the pidfd we own it by default */ + s->wakeup = WAKEUP_EVENT_SOURCE; s->child.options = options; s->child.callback = callback; s->userdata = userdata; s->enabled = SD_EVENT_ONESHOT; - /* We always take a pidfd here if we can, even if we wait for anything else than WEXITED, so that we - * pin the PID, and make regular waitid() handling race-free. */ - - if (shall_use_pidfd()) { - s->child.pidfd = pidfd_open(pid, 0); - if (s->child.pidfd < 0) { - /* Propagate errors unless the syscall is not supported or blocked */ - if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno)) - return -errno; - } else - s->child.pidfd_owned = true; /* If we allocate the pidfd we own it by default */ - } else - s->child.pidfd = -EBADF; - if (EVENT_SOURCE_WATCH_PIDFD(s)) { - /* We have a pidfd and we only want to watch for exit */ + /* We only want to watch for exit */ r = source_child_pidfd_register(s, s->enabled); if (r < 0) return r; } else { - /* We have no pidfd or we shall wait for some other event than WEXITED */ + /* We shall wait for some other event than WEXITED */ r = event_make_signal_data(e, SIGCHLD, NULL); if (r < 0) return r; @@ -1686,7 +1677,6 @@ _public_ int sd_event_add_child_pidfd( sd_event_child_handler_t callback, void *userdata) { - _cleanup_(source_freep) sd_event_source *s = NULL; pid_t pid; int r; @@ -1727,17 +1717,12 @@ _public_ int sd_event_add_child_pidfd( s->wakeup = WAKEUP_EVENT_SOURCE; s->child.pidfd = pidfd; - s->child.pid = pid; s->child.options = options; s->child.callback = callback; s->child.pidfd_owned = false; /* If we got the pidfd passed in we don't own it by default (similar to the IO fd case) */ s->userdata = userdata; s->enabled = SD_EVENT_ONESHOT; - r = hashmap_put(e->child_sources, PID_TO_PTR(pid), s); - if (r < 0) - return r; - if (EVENT_SOURCE_WATCH_PIDFD(s)) { /* We only want to watch for WEXITED */ r = source_child_pidfd_register(s, s->enabled); @@ -1752,6 +1737,11 @@ _public_ int sd_event_add_child_pidfd( e->need_process_child = true; } + r = hashmap_put(e->child_sources, PID_TO_PTR(pid), s); + if (r < 0) + return r; + + s->child.pid = pid; e->n_online_child_sources++; if (ret) @@ -2280,6 +2270,7 @@ static void event_free_inode_data( assert_se(hashmap_remove(d->inotify_data->inodes, d) == d); } + free(d->path); free(d); } @@ -2423,7 +2414,7 @@ static int inode_data_realize_watch(sd_event *e, struct inode_data *d) { wd = inotify_add_watch_fd(d->inotify_data->fd, d->fd, combined_mask); if (wd < 0) - return -errno; + return wd; if (d->wd < 0) { r = hashmap_put(d->inotify_data->wd, INT_TO_PTR(wd), d); @@ -2445,6 +2436,7 @@ static int inode_data_realize_watch(sd_event *e, struct inode_data *d) { return 1; } +#if 0 /* NM_IGNORED */ static int inotify_exit_callback(sd_event_source *s, const struct inotify_event *event, void *userdata) { assert(s); @@ -2520,6 +2512,15 @@ static int event_add_inotify_fd_internal( } LIST_PREPEND(to_close, e->inode_data_to_close_list, inode_data); + + _cleanup_free_ char *path = NULL; + r = fd_get_path(inode_data->fd, &path); + if (r < 0 && r != -ENOSYS) { /* The path is optional, hence ignore -ENOSYS. */ + event_gc_inode_data(e, inode_data); + return r; + } + + free_and_replace(inode_data->path, path); } /* Link our event source to the inode data object */ @@ -2579,6 +2580,7 @@ _public_ int sd_event_add_inotify( return r; } +#endif /* NM_IGNORED */ static sd_event_source* event_source_free(sd_event_source *s) { if (!s) @@ -2609,18 +2611,18 @@ _public_ int sd_event_source_set_description(sd_event_source *s, const char *des return free_and_strdup(&s->description, description); } -_public_ int sd_event_source_get_description(sd_event_source *s, const char **description) { +_public_ int sd_event_source_get_description(sd_event_source *s, const char **ret) { assert_return(s, -EINVAL); - assert_return(description, -EINVAL); + assert_return(ret, -EINVAL); if (!s->description) return -ENXIO; - *description = s->description; + *ret = s->description; return 0; } -_public_ sd_event *sd_event_source_get_event(sd_event_source *s) { +_public_ sd_event* sd_event_source_get_event(sd_event_source *s) { assert_return(s, NULL); assert_return(!event_origin_changed(s->event), NULL); @@ -2645,7 +2647,7 @@ _public_ int sd_event_source_get_io_fd(sd_event_source *s) { } _public_ int sd_event_source_set_io_fd(sd_event_source *s, int fd) { - int r; + int saved_fd, r; assert_return(s, -EINVAL); assert_return(fd >= 0, -EBADF); @@ -2655,16 +2657,12 @@ _public_ int sd_event_source_set_io_fd(sd_event_source *s, int fd) { if (s->io.fd == fd) return 0; - if (event_source_is_offline(s)) { - s->io.fd = fd; - s->io.registered = false; - } else { - int saved_fd; + saved_fd = s->io.fd; + s->io.fd = fd; - saved_fd = s->io.fd; - assert(s->io.registered); + assert(event_source_is_offline(s) == !s->io.registered); - s->io.fd = fd; + if (s->io.registered) { s->io.registered = false; r = source_io_register(s, s->enabled, s->io.events); @@ -2677,6 +2675,9 @@ _public_ int sd_event_source_set_io_fd(sd_event_source *s, int fd) { (void) epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, saved_fd, NULL); } + if (s->io.owned) + safe_close(saved_fd); + return 0; } @@ -2697,13 +2698,13 @@ _public_ int sd_event_source_set_io_fd_own(sd_event_source *s, int own) { return 0; } -_public_ int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events) { +_public_ int sd_event_source_get_io_events(sd_event_source *s, uint32_t *ret) { assert_return(s, -EINVAL); - assert_return(events, -EINVAL); + assert_return(ret, -EINVAL); assert_return(s->type == SOURCE_IO, -EDOM); assert_return(!event_origin_changed(s->event), -ECHILD); - *events = s->io.events; + *ret = s->io.events; return 0; } @@ -2735,14 +2736,14 @@ _public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events) return 0; } -_public_ int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents) { +_public_ int sd_event_source_get_io_revents(sd_event_source *s, uint32_t *ret) { assert_return(s, -EINVAL); - assert_return(revents, -EINVAL); + assert_return(ret, -EINVAL); assert_return(s->type == SOURCE_IO, -EDOM); assert_return(s->pending, -ENODATA); assert_return(!event_origin_changed(s->event), -ECHILD); - *revents = s->io.revents; + *ret = s->io.revents; return 0; } @@ -2754,11 +2755,12 @@ _public_ int sd_event_source_get_signal(sd_event_source *s) { return s->signal.sig; } -_public_ int sd_event_source_get_priority(sd_event_source *s, int64_t *priority) { +_public_ int sd_event_source_get_priority(sd_event_source *s, int64_t *ret) { assert_return(s, -EINVAL); + assert_return(ret, -EINVAL); assert_return(!event_origin_changed(s->event), -ECHILD); - *priority = s->priority; + *ret = s->priority; return 0; } @@ -2806,6 +2808,13 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority) } LIST_PREPEND(to_close, s->event->inode_data_to_close_list, new_inode_data); + + _cleanup_free_ char *path = NULL; + r = fd_get_path(new_inode_data->fd, &path); + if (r < 0 && r != -ENOSYS) + goto fail; + + free_and_replace(new_inode_data->path, path); } /* Move the event source to the new inode data structure */ @@ -3092,13 +3101,13 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { return 0; } -_public_ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) { +_public_ int sd_event_source_get_time(sd_event_source *s, uint64_t *ret) { assert_return(s, -EINVAL); - assert_return(usec, -EINVAL); + assert_return(ret, -EINVAL); assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); assert_return(!event_origin_changed(s->event), -ECHILD); - *usec = s->time.next; + *ret = s->time.next; return 0; } @@ -3142,13 +3151,13 @@ _public_ int sd_event_source_set_time_relative(sd_event_source *s, uint64_t usec return sd_event_source_set_time(s, usec); } -_public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec) { +_public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *ret) { assert_return(s, -EINVAL); - assert_return(usec, -EINVAL); + assert_return(ret, -EINVAL); assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); assert_return(!event_origin_changed(s->event), -ECHILD); - *usec = s->time.accuracy; + *ret = s->time.accuracy; return 0; } @@ -3174,23 +3183,23 @@ _public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec return 0; } -_public_ int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock) { +_public_ int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *ret) { assert_return(s, -EINVAL); - assert_return(clock, -EINVAL); + assert_return(ret, -EINVAL); assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); assert_return(!event_origin_changed(s->event), -ECHILD); - *clock = event_source_type_to_clock(s->type); + *ret = event_source_type_to_clock(s->type); return 0; } -_public_ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) { +_public_ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *ret) { assert_return(s, -EINVAL); - assert_return(pid, -EINVAL); + assert_return(ret, -EINVAL); assert_return(s->type == SOURCE_CHILD, -EDOM); assert_return(!event_origin_changed(s->event), -ECHILD); - *pid = s->child.pid; + *ret = s->child.pid; return 0; } @@ -3225,12 +3234,10 @@ _public_ int sd_event_source_send_child_signal(sd_event_source *s, int sig, cons if (si) copy = *si; - if (pidfd_send_signal(s->child.pidfd, sig, si ? © : NULL, 0) < 0) { - /* Let's propagate the error only if the system call is not implemented or prohibited */ - if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno)) - return -errno; - } else - return 0; + if (pidfd_send_signal(s->child.pidfd, sig, si ? © : NULL, 0) < 0) + return -errno; + + return 0; } /* Flags are only supported for pidfd_send_signal(), not for rt_sigqueueinfo(), hence let's refuse @@ -3290,13 +3297,29 @@ _public_ int sd_event_source_set_child_process_own(sd_event_source *s, int own) return 0; } -_public_ int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *mask) { +_public_ int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *ret) { + assert_return(s, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(s->type == SOURCE_INOTIFY, -EDOM); + assert_return(!event_origin_changed(s->event), -ECHILD); + + *ret = s->inotify.mask; + return 0; +} + +_public_ int sd_event_source_get_inotify_path(sd_event_source *s, const char **ret) { assert_return(s, -EINVAL); - assert_return(mask, -EINVAL); + assert_return(ret, -EINVAL); assert_return(s->type == SOURCE_INOTIFY, -EDOM); assert_return(!event_origin_changed(s->event), -ECHILD); - *mask = s->inotify.mask; + if (!s->inotify.inode_data) + return -ESTALE; /* already disconnected. */ + + if (!s->inotify.inode_data->path) + return -ENOSYS; /* /proc was not mounted? */ + + *ret = s->inotify.inode_data->path; return 0; } @@ -3839,7 +3862,8 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events, i if (_unlikely_(n != sizeof(si))) return -EIO; - assert(SIGNAL_VALID(si.ssi_signo)); + if (_unlikely_(!SIGNAL_VALID(si.ssi_signo))) + return -EIO; if (e->signal_sources) s = e->signal_sources[si.ssi_signo]; @@ -4540,7 +4564,7 @@ static int epoll_wait_usec( /* epoll_pwait2() was added to Linux 5.11 (2021-02-14) and to glibc in 2.35 (2022-02-03). In contrast * to other syscalls we don't bother with our own fallback syscall wrappers on old libcs, since this * is not that obvious to implement given the libc and kernel definitions differ in the last - * argument. Moreover, the only reason to use it is the more accurate time-outs (which is not a + * argument. Moreover, the only reason to use it is the more accurate timeouts (which is not a * biggie), let's hence rely on glibc's definitions, and fallback to epoll_pwait() when that's * missing. */ @@ -4825,13 +4849,13 @@ _public_ int sd_event_dispatch(sd_event *e) { static void event_log_delays(sd_event *e) { char b[ELEMENTSOF(e->delays) * DECIMAL_STR_MAX(unsigned) + 1], *p; - size_t l, i; + size_t l; p = b; l = sizeof(b); - for (i = 0; i < ELEMENTSOF(e->delays); i++) { - l = strpcpyf(&p, l, "%u ", e->delays[i]); - e->delays[i] = 0; + FOREACH_ELEMENT(delay, e->delays) { + l = strpcpyf(&p, l, "%u ", *delay); + *delay = 0; } log_debug("Event loop iterations: %s", b); } @@ -4892,7 +4916,6 @@ _public_ int sd_event_loop(sd_event *e) { assert_return(!event_origin_changed(e), -ECHILD); assert_return(e->state == SD_EVENT_INITIAL, -EBUSY); - PROTECT_EVENT(e); while (e->state != SD_EVENT_FINISHED) { @@ -4920,7 +4943,7 @@ _public_ int sd_event_get_state(sd_event *e) { return e->state; } -_public_ int sd_event_get_exit_code(sd_event *e, int *code) { +_public_ int sd_event_get_exit_code(sd_event *e, int *ret) { assert_return(e, -EINVAL); assert_return(e = event_resolve(e), -ENOPKG); assert_return(!event_origin_changed(e), -ECHILD); @@ -4928,8 +4951,8 @@ _public_ int sd_event_get_exit_code(sd_event *e, int *code) { if (!e->exit_requested) return -ENODATA; - if (code) - *code = e->exit_code; + if (ret) + *ret = e->exit_code; return 0; } @@ -4945,10 +4968,10 @@ _public_ int sd_event_exit(sd_event *e, int code) { return 0; } -_public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) { +_public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *ret) { assert_return(e, -EINVAL); assert_return(e = event_resolve(e), -ENOPKG); - assert_return(usec, -EINVAL); + assert_return(ret, -EINVAL); assert_return(!event_origin_changed(e), -ECHILD); if (!TRIPLE_TIMESTAMP_HAS_CLOCK(clock)) @@ -4956,11 +4979,11 @@ _public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) { if (!triple_timestamp_is_set(&e->timestamp)) { /* Implicitly fall back to now() if we never ran before and thus have no cached time. */ - *usec = now(clock); + *ret = now(clock); return 1; } - *usec = triple_timestamp_by_clock(&e->timestamp, clock); + *ret = triple_timestamp_by_clock(&e->timestamp, clock); return 0; } @@ -4989,18 +5012,17 @@ _public_ int sd_event_default(sd_event **ret) { } #if 0 /* NM_IGNORED */ -_public_ int sd_event_get_tid(sd_event *e, pid_t *tid) { +_public_ int sd_event_get_tid(sd_event *e, pid_t *ret) { assert_return(e, -EINVAL); assert_return(e = event_resolve(e), -ENOPKG); - assert_return(tid, -EINVAL); + assert_return(ret, -EINVAL); assert_return(!event_origin_changed(e), -ECHILD); - if (e->tid != 0) { - *tid = e->tid; - return 0; - } + if (e->tid == 0) + return -ENXIO; - return -ENXIO; + *ret = e->tid; + return 0; } _public_ int sd_event_set_watchdog(sd_event *e, int b) { @@ -5230,6 +5252,9 @@ _public_ int sd_event_set_signal_exit(sd_event *e, int b) { int r; assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_origin_changed(e), -ECHILD); if (b) { /* We want to maintain pointers to these event sources, so that we can destroy them when told @@ -5241,7 +5266,7 @@ _public_ int sd_event_set_signal_exit(sd_event *e, int b) { if (r < 0) return r; - assert(sd_event_source_set_floating(e->sigint_event_source, true) >= 0); + assert_se(sd_event_source_set_floating(e->sigint_event_source, true) >= 0); change = true; } @@ -5249,26 +5274,26 @@ _public_ int sd_event_set_signal_exit(sd_event *e, int b) { r = sd_event_add_signal(e, &e->sigterm_event_source, SIGTERM | SD_EVENT_SIGNAL_PROCMASK, NULL, NULL); if (r < 0) { if (change) { - assert(sd_event_source_set_floating(e->sigint_event_source, false) >= 0); + assert_se(sd_event_source_set_floating(e->sigint_event_source, false) >= 0); e->sigint_event_source = sd_event_source_unref(e->sigint_event_source); } return r; } - assert(sd_event_source_set_floating(e->sigterm_event_source, true) >= 0); + assert_se(sd_event_source_set_floating(e->sigterm_event_source, true) >= 0); change = true; } } else { if (e->sigint_event_source) { - assert(sd_event_source_set_floating(e->sigint_event_source, false) >= 0); + assert_se(sd_event_source_set_floating(e->sigint_event_source, false) >= 0); e->sigint_event_source = sd_event_source_unref(e->sigint_event_source); change = true; } if (e->sigterm_event_source) { - assert(sd_event_source_set_floating(e->sigterm_event_source, false) >= 0); + assert_se(sd_event_source_set_floating(e->sigterm_event_source, false) >= 0); e->sigterm_event_source = sd_event_source_unref(e->sigterm_event_source); change = true; } diff --git a/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.c b/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.c index 58173055..6d515a94 100644 --- a/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.c +++ b/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.c @@ -11,6 +11,8 @@ #include "hexdecoct.h" #include "id128-util.h" #include "io-util.h" +#include "namespace-util.h" +#include "process-util.h" #include "sha256.h" #include "stdio-util.h" #include "string-util.h" @@ -273,4 +275,65 @@ sd_id128_t id128_digest(const void *data, size_t size) { return id128_make_v4_uuid(id); } + +int id128_get_boot_for_machine(const char *machine, sd_id128_t *ret) { + _cleanup_close_ int pidnsfd = -EBADF, mntnsfd = -EBADF, rootfd = -EBADF; + _cleanup_close_pair_ int pair[2] = EBADF_PAIR; + pid_t pid, child; + sd_id128_t id; + ssize_t k; + int r; + + assert(ret); + + if (isempty(machine)) + return sd_id128_get_boot(ret); + + r = container_get_leader(machine, &pid); + if (r < 0) + return r; + + r = namespace_open(pid, &pidnsfd, &mntnsfd, /* ret_netns_fd = */ NULL, /* ret_userns_fd = */ NULL, &rootfd); + if (r < 0) + return r; + + if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0) + return -errno; + + r = namespace_fork("(sd-bootidns)", "(sd-bootid)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL, + pidnsfd, mntnsfd, -1, -1, rootfd, &child); + if (r < 0) + return r; + if (r == 0) { + pair[0] = safe_close(pair[0]); + + r = id128_get_boot(&id); + if (r < 0) + _exit(EXIT_FAILURE); + + k = send(pair[1], &id, sizeof(id), MSG_NOSIGNAL); + if (k != sizeof(id)) + _exit(EXIT_FAILURE); + + _exit(EXIT_SUCCESS); + } + + pair[1] = safe_close(pair[1]); + + r = wait_for_terminate_and_check("(sd-bootidns)", child, 0); + if (r < 0) + return r; + if (r != EXIT_SUCCESS) + return -EIO; + + k = recv(pair[0], &id, sizeof(id), 0); + if (k != sizeof(id)) + return -EIO; + + if (sd_id128_is_null(id)) + return -EIO; + + *ret = id; + return 0; +} #endif /* NM_IGNORED */ diff --git a/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.h b/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.h index 53ba50a8..458d4307 100644 --- a/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.h +++ b/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.h @@ -49,6 +49,9 @@ int id128_get_product(sd_id128_t *ret); sd_id128_t id128_digest(const void *data, size_t size); +int id128_get_boot(sd_id128_t *ret); +int id128_get_boot_for_machine(const char *machine, sd_id128_t *ret); + /* A helper to check for the three relevant cases of "machine ID not initialized" */ #define ERRNO_IS_NEG_MACHINE_ID_UNSET(r) \ IN_SET(r, \ diff --git a/src/libnm-systemd-core/src/libsystemd/sd-id128/sd-id128.c b/src/libnm-systemd-core/src/libsystemd/sd-id128/sd-id128.c index ff0db776..9f6ef719 100644 --- a/src/libnm-systemd-core/src/libsystemd/sd-id128/sd-id128.c +++ b/src/libnm-systemd-core/src/libsystemd/sd-id128/sd-id128.c @@ -15,6 +15,7 @@ #include "hmac.h" #include "id128-util.h" #include "io-util.h" +#include "keyring-util.h" #include "macro.h" #include "missing_syscall.h" #include "missing_threads.h" @@ -176,14 +177,24 @@ int id128_get_machine(const char *root, sd_id128_t *ret) { } #endif /* NM_IGNORED */ +int id128_get_boot(sd_id128_t *ret) { + int r; + + assert(ret); + + r = id128_read("/proc/sys/kernel/random/boot_id", ID128_FORMAT_UUID | ID128_REFUSE_NULL, ret); + if (r == -ENOENT && proc_mounted() == 0) + return -ENOSYS; + + return r; +} + _public_ int sd_id128_get_boot(sd_id128_t *ret) { static thread_local sd_id128_t saved_boot_id = {}; int r; if (sd_id128_is_null(saved_boot_id)) { - r = id128_read("/proc/sys/kernel/random/boot_id", ID128_FORMAT_UUID | ID128_REFUSE_NULL, &saved_boot_id); - if (r == -ENOENT && proc_mounted() == 0) - return -ENOSYS; + r = id128_get_boot(&saved_boot_id); if (r < 0) return r; } @@ -199,7 +210,6 @@ static int get_invocation_from_keyring(sd_id128_t *ret) { char *d, *p, *g, *u, *e; unsigned long perms; key_serial_t key; - size_t sz = 256; uid_t uid; gid_t gid; int r, c; @@ -218,24 +228,9 @@ static int get_invocation_from_keyring(sd_id128_t *ret) { return -errno; } - for (;;) { - description = new(char, sz); - if (!description) - return -ENOMEM; - - c = keyctl(KEYCTL_DESCRIBE, key, (unsigned long) description, sz, 0); - if (c < 0) - return -errno; - - if ((size_t) c <= sz) - break; - - sz = c; - free(description); - } - - /* The kernel returns a final NUL in the string, verify that. */ - assert(description[c-1] == 0); + r = keyring_describe(key, &description); + if (r < 0) + return r; /* Chop off the final description string */ d = strrchr(description, ';'); @@ -387,4 +382,17 @@ _public_ int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret) return sd_id128_get_app_specific(id, app_id, ret); } + +_public_ int sd_id128_get_invocation_app_specific(sd_id128_t app_id, sd_id128_t *ret) { + sd_id128_t id; + int r; + + assert_return(ret, -EINVAL); + + r = sd_id128_get_invocation(&id); + if (r < 0) + return r; + + return sd_id128_get_app_specific(id, app_id, ret); +} #endif /* NM_IGNORED */ diff --git a/src/libnm-systemd-core/src/systemd/_sd-common.h b/src/libnm-systemd-core/src/systemd/_sd-common.h index d4381d90..5792dd81 100644 --- a/src/libnm-systemd-core/src/systemd/_sd-common.h +++ b/src/libnm-systemd-core/src/systemd/_sd-common.h @@ -45,6 +45,10 @@ typedef void (*_sd_destroy_t)(void *userdata); # define _sd_pure_ __attribute__((__pure__)) #endif +#ifndef _sd_const_ +# define _sd_const_ __attribute__((__const__)) +#endif + /* Note that strictly speaking __deprecated__ has been available before GCC 6. However, starting with GCC 6 * it also works on enum values, which we are interested in. Since this is a developer-facing feature anyway * (as opposed to build engineer-facing), let's hence conditionalize this to gcc 6, given that the developers @@ -105,4 +109,11 @@ typedef void (*_sd_destroy_t)(void *userdata); _SD_##id##_INT64_MIN = INT64_MIN, \ _SD_##id##_INT64_MAX = INT64_MAX +/* In GCC 14 (C23) we can force enums to have the right types, and not solely rely on language extensions anymore */ +#if ((__GNUC__ >= 14) || (__STDC_VERSION__ >= 202311L)) && !defined(__cplusplus) +# define _SD_ENUM_TYPE_S64(id) id : int64_t +#else +# define _SD_ENUM_TYPE_S64(id) id +#endif + #endif diff --git a/src/libnm-systemd-core/src/systemd/sd-device.h b/src/libnm-systemd-core/src/systemd/sd-device.h index b67ec0f3..f627ae6d 100644 --- a/src/libnm-systemd-core/src/systemd/sd-device.h +++ b/src/libnm-systemd-core/src/systemd/sd-device.h @@ -34,7 +34,7 @@ typedef struct sd_device sd_device; typedef struct sd_device_enumerator sd_device_enumerator; typedef struct sd_device_monitor sd_device_monitor; -__extension__ typedef enum sd_device_action_t { +__extension__ typedef enum _SD_ENUM_TYPE_S64(sd_device_action_t) { SD_DEVICE_ADD, SD_DEVICE_REMOVE, SD_DEVICE_CHANGE, @@ -74,6 +74,7 @@ int sd_device_get_parent_with_subsystem_devtype(sd_device *child, const char *su int sd_device_get_syspath(sd_device *device, const char **ret); int sd_device_get_subsystem(sd_device *device, const char **ret); +int sd_device_get_driver_subsystem(sd_device *device, const char **ret); int sd_device_get_devtype(sd_device *device, const char **ret); int sd_device_get_devnum(sd_device *device, dev_t *devnum); int sd_device_get_ifindex(sd_device *device, int *ifindex); @@ -85,21 +86,22 @@ int sd_device_get_sysnum(sd_device *device, const char **ret); int sd_device_get_action(sd_device *device, sd_device_action_t *ret); int sd_device_get_seqnum(sd_device *device, uint64_t *ret); int sd_device_get_diskseq(sd_device *device, uint64_t *ret); +int sd_device_get_device_id(sd_device *device, const char **ret); int sd_device_get_is_initialized(sd_device *device); int sd_device_get_usec_initialized(sd_device *device, uint64_t *ret); int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *ret); -const char *sd_device_get_tag_first(sd_device *device); -const char *sd_device_get_tag_next(sd_device *device); -const char *sd_device_get_current_tag_first(sd_device *device); -const char *sd_device_get_current_tag_next(sd_device *device); -const char *sd_device_get_devlink_first(sd_device *device); -const char *sd_device_get_devlink_next(sd_device *device); -const char *sd_device_get_property_first(sd_device *device, const char **value); -const char *sd_device_get_property_next(sd_device *device, const char **value); -const char *sd_device_get_sysattr_first(sd_device *device); -const char *sd_device_get_sysattr_next(sd_device *device); +const char* sd_device_get_tag_first(sd_device *device); +const char* sd_device_get_tag_next(sd_device *device); +const char* sd_device_get_current_tag_first(sd_device *device); +const char* sd_device_get_current_tag_next(sd_device *device); +const char* sd_device_get_devlink_first(sd_device *device); +const char* sd_device_get_devlink_next(sd_device *device); +const char* sd_device_get_property_first(sd_device *device, const char **value); +const char* sd_device_get_property_next(sd_device *device, const char **value); +const char* sd_device_get_sysattr_first(sd_device *device); +const char* sd_device_get_sysattr_next(sd_device *device); sd_device *sd_device_get_child_first(sd_device *device, const char **ret_suffix); sd_device *sd_device_get_child_next(sd_device *device, const char **ret_suffix); @@ -135,6 +137,7 @@ int sd_device_enumerator_add_nomatch_sysname(sd_device_enumerator *enumerator, c int sd_device_enumerator_add_match_tag(sd_device_enumerator *enumerator, const char *tag); int sd_device_enumerator_add_match_parent(sd_device_enumerator *enumerator, sd_device *parent); int sd_device_enumerator_allow_uninitialized(sd_device_enumerator *enumerator); +int sd_device_enumerator_add_all_parents(sd_device_enumerator *enumerator); /* device monitor */ @@ -142,6 +145,9 @@ int sd_device_monitor_new(sd_device_monitor **ret); sd_device_monitor *sd_device_monitor_ref(sd_device_monitor *m); sd_device_monitor *sd_device_monitor_unref(sd_device_monitor *m); +int sd_device_monitor_get_fd(sd_device_monitor *m); +int sd_device_monitor_get_events(sd_device_monitor *m); +int sd_device_monitor_get_timeout(sd_device_monitor *m, uint64_t *ret); int sd_device_monitor_set_receive_buffer_size(sd_device_monitor *m, size_t size); int sd_device_monitor_attach_event(sd_device_monitor *m, sd_event *event); int sd_device_monitor_detach_event(sd_device_monitor *m); @@ -149,8 +155,10 @@ sd_event *sd_device_monitor_get_event(sd_device_monitor *m); sd_event_source *sd_device_monitor_get_event_source(sd_device_monitor *m); int sd_device_monitor_set_description(sd_device_monitor *m, const char *description); int sd_device_monitor_get_description(sd_device_monitor *m, const char **ret); +int sd_device_monitor_is_running(sd_device_monitor *m); int sd_device_monitor_start(sd_device_monitor *m, sd_device_monitor_handler_t callback, void *userdata); int sd_device_monitor_stop(sd_device_monitor *m); +int sd_device_monitor_receive(sd_device_monitor *m, sd_device **ret); int sd_device_monitor_filter_add_match_subsystem_devtype(sd_device_monitor *m, const char *subsystem, const char *devtype); int sd_device_monitor_filter_add_match_tag(sd_device_monitor *m, const char *tag); diff --git a/src/libnm-systemd-core/src/systemd/sd-dhcp6-lease.h b/src/libnm-systemd-core/src/systemd/sd-dhcp6-lease.h index e18d5781..d6bcceb2 100644 --- a/src/libnm-systemd-core/src/systemd/sd-dhcp6-lease.h +++ b/src/libnm-systemd-core/src/systemd/sd-dhcp6-lease.h @@ -30,6 +30,7 @@ _SD_BEGIN_DECLARATIONS; typedef struct sd_dhcp6_lease sd_dhcp6_lease; +typedef struct sd_dns_resolver sd_dns_resolver; int sd_dhcp6_lease_get_timestamp(sd_dhcp6_lease *lease, clockid_t clock, uint64_t *ret); int sd_dhcp6_lease_get_t1(sd_dhcp6_lease *lease, uint64_t *ret); @@ -74,6 +75,7 @@ int sd_dhcp6_lease_get_pd_lifetime_timestamp( int sd_dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease); int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, const struct in6_addr **ret); +int sd_dhcp6_lease_get_dnr(sd_dhcp6_lease *lease, sd_dns_resolver **ret); int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***ret); int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease, const struct in6_addr **ret); int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ret); diff --git a/src/libnm-systemd-core/src/systemd/sd-dhcp6-protocol.h b/src/libnm-systemd-core/src/systemd/sd-dhcp6-protocol.h index 78c80f7c..b1d9ca1f 100644 --- a/src/libnm-systemd-core/src/systemd/sd-dhcp6-protocol.h +++ b/src/libnm-systemd-core/src/systemd/sd-dhcp6-protocol.h @@ -165,8 +165,9 @@ enum { SD_DHCP6_OPTION_SLAP_QUAD = 140, /* RFC 8948 */ SD_DHCP6_OPTION_V6_DOTS_RI = 141, /* RFC 8973 */ SD_DHCP6_OPTION_V6_DOTS_ADDRESS = 142, /* RFC 8973 */ - SD_DHCP6_OPTION_IPV6_ADDRESS_ANDSF = 143 /* RFC 6153 */ - /* option codes 144-65535 are unassigned */ + SD_DHCP6_OPTION_IPV6_ADDRESS_ANDSF = 143, /* RFC 6153 */ + SD_DHCP6_OPTION_V6_DNR = 144 /* RFC 9463 */ + /* option codes 145-65535 are unassigned */ }; _SD_END_DECLARATIONS; diff --git a/src/libnm-systemd-core/src/systemd/sd-event.h b/src/libnm-systemd-core/src/systemd/sd-event.h index 49d69759..1e19dd4e 100644 --- a/src/libnm-systemd-core/src/systemd/sd-event.h +++ b/src/libnm-systemd-core/src/systemd/sd-event.h @@ -108,12 +108,12 @@ int sd_event_run(sd_event *e, uint64_t usec); int sd_event_loop(sd_event *e); int sd_event_exit(sd_event *e, int code); -int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec); +int sd_event_now(sd_event *e, clockid_t clock, uint64_t *ret); int sd_event_get_fd(sd_event *e); int sd_event_get_state(sd_event *e); -int sd_event_get_tid(sd_event *e, pid_t *tid); -int sd_event_get_exit_code(sd_event *e, int *code); +int sd_event_get_tid(sd_event *e, pid_t *ret); +int sd_event_get_exit_code(sd_event *e, int *ret); int sd_event_set_watchdog(sd_event *e, int b); int sd_event_get_watchdog(sd_event *e); int sd_event_get_iteration(sd_event *e, uint64_t *ret); @@ -123,33 +123,33 @@ sd_event_source* sd_event_source_ref(sd_event_source *s); sd_event_source* sd_event_source_unref(sd_event_source *s); sd_event_source* sd_event_source_disable_unref(sd_event_source *s); -sd_event *sd_event_source_get_event(sd_event_source *s); +sd_event* sd_event_source_get_event(sd_event_source *s); void* sd_event_source_get_userdata(sd_event_source *s); void* sd_event_source_set_userdata(sd_event_source *s, void *userdata); int sd_event_source_set_description(sd_event_source *s, const char *description); -int sd_event_source_get_description(sd_event_source *s, const char **description); +int sd_event_source_get_description(sd_event_source *s, const char **ret); int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback); int sd_event_source_get_pending(sd_event_source *s); -int sd_event_source_get_priority(sd_event_source *s, int64_t *priority); +int sd_event_source_get_priority(sd_event_source *s, int64_t *ret); int sd_event_source_set_priority(sd_event_source *s, int64_t priority); -int sd_event_source_get_enabled(sd_event_source *s, int *enabled); +int sd_event_source_get_enabled(sd_event_source *s, int *ret); int sd_event_source_set_enabled(sd_event_source *s, int enabled); int sd_event_source_get_io_fd(sd_event_source *s); int sd_event_source_set_io_fd(sd_event_source *s, int fd); int sd_event_source_get_io_fd_own(sd_event_source *s); int sd_event_source_set_io_fd_own(sd_event_source *s, int own); -int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events); +int sd_event_source_get_io_events(sd_event_source *s, uint32_t *ret); int sd_event_source_set_io_events(sd_event_source *s, uint32_t events); -int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents); -int sd_event_source_get_time(sd_event_source *s, uint64_t *usec); +int sd_event_source_get_io_revents(sd_event_source *s, uint32_t *ret); +int sd_event_source_get_time(sd_event_source *s, uint64_t *ret); int sd_event_source_set_time(sd_event_source *s, uint64_t usec); int sd_event_source_set_time_relative(sd_event_source *s, uint64_t usec); -int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec); +int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *ret); int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec); -int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock); +int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *ret); int sd_event_source_get_signal(sd_event_source *s); -int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid); +int sd_event_source_get_child_pid(sd_event_source *s, pid_t *ret); int sd_event_source_get_child_pidfd(sd_event_source *s); int sd_event_source_get_child_pidfd_own(sd_event_source *s); int sd_event_source_set_child_pidfd_own(sd_event_source *s, int own); @@ -161,6 +161,7 @@ int sd_event_source_send_child_signal(sd_event_source *s, int sig, const siginfo int sd_event_source_send_child_signal(sd_event_source *s, int sig, const void *si, unsigned flags); #endif int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *ret); +int sd_event_source_get_inotify_path(sd_event_source *s, const char **ret); int sd_event_source_set_memory_pressure_type(sd_event_source *e, const char *ty); int sd_event_source_set_memory_pressure_period(sd_event_source *s, uint64_t threshold_usec, uint64_t window_usec); int sd_event_source_set_destroy_callback(sd_event_source *s, sd_event_destroy_t callback); diff --git a/src/libnm-systemd-core/src/systemd/sd-id128.h b/src/libnm-systemd-core/src/systemd/sd-id128.h index a984a9d8..7be69040 100644 --- a/src/libnm-systemd-core/src/systemd/sd-id128.h +++ b/src/libnm-systemd-core/src/systemd/sd-id128.h @@ -37,8 +37,8 @@ union sd_id128 { #define SD_ID128_STRING_MAX 33U #define SD_ID128_UUID_STRING_MAX 37U -char *sd_id128_to_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_STRING_MAX]); -char *sd_id128_to_uuid_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_UUID_STRING_MAX]); +char* sd_id128_to_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_STRING_MAX]); +char* sd_id128_to_uuid_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_UUID_STRING_MAX]); int sd_id128_from_string(const char *s, sd_id128_t *ret); #define SD_ID128_TO_STRING(id) sd_id128_to_string((id), (char[SD_ID128_STRING_MAX]) {}) @@ -53,6 +53,7 @@ int sd_id128_get_invocation(sd_id128_t *ret); int sd_id128_get_app_specific(sd_id128_t base, sd_id128_t app_id, sd_id128_t *ret); int sd_id128_get_machine_app_specific(sd_id128_t app_id, sd_id128_t *ret); int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret); +int sd_id128_get_invocation_app_specific(sd_id128_t app_id, sd_id128_t *ret); #define SD_ID128_ARRAY(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) \ { .bytes = { 0x##v0, 0x##v1, 0x##v2, 0x##v3, 0x##v4, 0x##v5, 0x##v6, 0x##v7, \ @@ -116,24 +117,24 @@ int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret); #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) { +_sd_const_ static __inline__ int sd_id128_equal(sd_id128_t a, sd_id128_t b) { return a.qwords[0] == b.qwords[0] && a.qwords[1] == b.qwords[1]; } int sd_id128_string_equal(const char *s, sd_id128_t id); -_sd_pure_ static __inline__ int sd_id128_is_null(sd_id128_t a) { +_sd_const_ static __inline__ int sd_id128_is_null(sd_id128_t a) { return a.qwords[0] == 0 && a.qwords[1] == 0; } -_sd_pure_ static __inline__ int sd_id128_is_allf(sd_id128_t a) { +_sd_const_ static __inline__ int sd_id128_is_allf(sd_id128_t a) { return a.qwords[0] == UINT64_C(0xFFFFFFFFFFFFFFFF) && a.qwords[1] == UINT64_C(0xFFFFFFFFFFFFFFFF); } #define SD_ID128_NULL ((const sd_id128_t) { .qwords = { 0, 0 }}) #define SD_ID128_ALLF ((const sd_id128_t) { .qwords = { UINT64_C(0xFFFFFFFFFFFFFFFF), UINT64_C(0xFFFFFFFFFFFFFFFF) }}) -_sd_pure_ static __inline__ int sd_id128_in_setv(sd_id128_t a, va_list ap) { +_sd_const_ static __inline__ int sd_id128_in_setv(sd_id128_t a, va_list ap) { for (;;) { sd_id128_t b = va_arg(ap, sd_id128_t); @@ -145,7 +146,7 @@ _sd_pure_ static __inline__ int sd_id128_in_setv(sd_id128_t a, va_list ap) { } } -_sd_pure_ static __inline__ int sd_id128_in_set_sentinel(sd_id128_t a, ...) { +_sd_const_ static __inline__ int sd_id128_in_set_sentinel(sd_id128_t a, ...) { va_list ap; int r; diff --git a/src/libnm-systemd-core/src/systemd/sd-ndisc.h b/src/libnm-systemd-core/src/systemd/sd-ndisc.h index 5f4f6caf..85fcf6bc 100644 --- a/src/libnm-systemd-core/src/systemd/sd-ndisc.h +++ b/src/libnm-systemd-core/src/systemd/sd-ndisc.h @@ -26,7 +26,9 @@ #include <sys/types.h> #include "sd-event.h" +#include "sd-ndisc-neighbor.h" #include "sd-ndisc-protocol.h" +#include "sd-ndisc-redirect.h" #include "sd-ndisc-router.h" #include "_sd-common.h" @@ -35,9 +37,11 @@ _SD_BEGIN_DECLARATIONS; typedef struct sd_ndisc sd_ndisc; -__extension__ typedef enum sd_ndisc_event_t { +__extension__ typedef enum _SD_ENUM_TYPE_S64(sd_ndisc_event_t) { SD_NDISC_EVENT_TIMEOUT, SD_NDISC_EVENT_ROUTER, + SD_NDISC_EVENT_NEIGHBOR, + SD_NDISC_EVENT_REDIRECT, _SD_NDISC_EVENT_MAX, _SD_NDISC_EVENT_INVALID = -EINVAL, _SD_ENUM_FORCE_S64(NDISC_EVENT) |