systemd: merge branch systemd into main

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1333
This commit is contained in:
Thomas Haller
2022-08-11 10:15:02 +02:00
31 changed files with 282 additions and 160 deletions

View File

@@ -66,20 +66,26 @@ int dhcp_validate_duid_len(DUIDType duid_type, size_t duid_len, bool strict) {
}
#if 0 /* NM_IGNORED */
static int dhcp_identifier_set_duid_llt(const uint8_t *addr, size_t addr_len, uint16_t arp_type, usec_t t, struct duid *ret_duid, size_t *ret_len) {
static int dhcp_identifier_set_duid_llt(
const struct hw_addr_data *hw_addr,
uint16_t arp_type,
usec_t t,
struct duid *ret_duid,
size_t *ret_len) {
uint16_t time_from_2000y;
assert(addr);
assert(hw_addr);
assert(ret_duid);
assert(ret_len);
if (addr_len == 0)
if (hw_addr->length == 0)
return -EOPNOTSUPP;
if (arp_type == ARPHRD_ETHER)
assert_return(addr_len == ETH_ALEN, -EINVAL);
assert_return(hw_addr->length == ETH_ALEN, -EINVAL);
else if (arp_type == ARPHRD_INFINIBAND)
assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
assert_return(hw_addr->length == INFINIBAND_ALEN, -EINVAL);
else
return -EOPNOTSUPP;
@@ -91,33 +97,38 @@ static int dhcp_identifier_set_duid_llt(const uint8_t *addr, size_t addr_len, ui
unaligned_write_be16(&ret_duid->type, DUID_TYPE_LLT);
unaligned_write_be16(&ret_duid->llt.htype, arp_type);
unaligned_write_be32(&ret_duid->llt.time, time_from_2000y);
memcpy(ret_duid->llt.haddr, addr, addr_len);
memcpy(ret_duid->llt.haddr, hw_addr->bytes, hw_addr->length);
*ret_len = offsetof(struct duid, llt.haddr) + addr_len;
*ret_len = offsetof(struct duid, llt.haddr) + hw_addr->length;
return 0;
}
static int dhcp_identifier_set_duid_ll(const uint8_t *addr, size_t addr_len, uint16_t arp_type, struct duid *ret_duid, size_t *ret_len) {
assert(addr);
static int dhcp_identifier_set_duid_ll(
const struct hw_addr_data *hw_addr,
uint16_t arp_type,
struct duid *ret_duid,
size_t *ret_len) {
assert(hw_addr);
assert(ret_duid);
assert(ret_len);
if (addr_len == 0)
if (hw_addr->length == 0)
return -EOPNOTSUPP;
if (arp_type == ARPHRD_ETHER)
assert_return(addr_len == ETH_ALEN, -EINVAL);
assert_return(hw_addr->length == ETH_ALEN, -EINVAL);
else if (arp_type == ARPHRD_INFINIBAND)
assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
assert_return(hw_addr->length == INFINIBAND_ALEN, -EINVAL);
else
return -EOPNOTSUPP;
unaligned_write_be16(&ret_duid->type, DUID_TYPE_LL);
unaligned_write_be16(&ret_duid->ll.htype, arp_type);
memcpy(ret_duid->ll.haddr, addr, addr_len);
memcpy(ret_duid->ll.haddr, hw_addr->bytes, hw_addr->length);
*ret_len = offsetof(struct duid, ll.haddr) + addr_len;
*ret_len = offsetof(struct duid, ll.haddr) + hw_addr->length;
return 0;
}
@@ -179,8 +190,7 @@ static int dhcp_identifier_set_duid_uuid(struct duid *ret_duid, size_t *ret_len)
int dhcp_identifier_set_duid(
DUIDType duid_type,
const uint8_t *addr,
size_t addr_len,
const struct hw_addr_data *hw_addr,
uint16_t arp_type,
usec_t llt_time,
bool test_mode,
@@ -189,11 +199,11 @@ int dhcp_identifier_set_duid(
switch (duid_type) {
case DUID_TYPE_LLT:
return dhcp_identifier_set_duid_llt(addr, addr_len, arp_type, llt_time, ret_duid, ret_len);
return dhcp_identifier_set_duid_llt(hw_addr, arp_type, llt_time, ret_duid, ret_len);
case DUID_TYPE_EN:
return dhcp_identifier_set_duid_en(test_mode, ret_duid, ret_len);
case DUID_TYPE_LL:
return dhcp_identifier_set_duid_ll(addr, addr_len, arp_type, ret_duid, ret_len);
return dhcp_identifier_set_duid_ll(hw_addr, arp_type, ret_duid, ret_len);
case DUID_TYPE_UUID:
return dhcp_identifier_set_duid_uuid(ret_duid, ret_len);
default:
@@ -204,8 +214,7 @@ int dhcp_identifier_set_duid(
int dhcp_identifier_set_iaid(
int ifindex,
const uint8_t *mac,
size_t mac_len,
const struct hw_addr_data *hw_addr,
bool legacy_unstable_byteorder,
bool use_mac,
void *ret) {
@@ -219,6 +228,10 @@ int dhcp_identifier_set_iaid(
uint64_t id;
int r;
assert(ifindex > 0);
assert(hw_addr);
assert(ret);
if (udev_available() && !use_mac) {
/* udev should be around */
@@ -247,7 +260,7 @@ int dhcp_identifier_set_iaid(
id = siphash24(name, strlen(name), HASH_KEY.bytes);
else
/* fall back to MAC address if no predictable name available */
id = siphash24(mac, mac_len, HASH_KEY.bytes);
id = siphash24(hw_addr->bytes, hw_addr->length, HASH_KEY.bytes);
id32 = (id & 0xffffffff) ^ (id >> 32);

View File

@@ -3,6 +3,7 @@
#include "sd-id128.h"
#include "ether-addr-util.h"
#include "macro.h"
#include "sparse-endian.h"
#include "time-util.h"
@@ -58,8 +59,7 @@ int dhcp_validate_duid_len(DUIDType duid_type, size_t duid_len, bool strict);
int dhcp_identifier_set_duid_en(bool test_mode, struct duid *ret_duid, size_t *ret_len);
int dhcp_identifier_set_duid(
DUIDType duid_type,
const uint8_t *addr,
size_t addr_len,
const struct hw_addr_data *hw_addr,
uint16_t arp_type,
usec_t llt_time,
bool test_mode,
@@ -67,8 +67,7 @@ int dhcp_identifier_set_duid(
size_t *ret_len);
int dhcp_identifier_set_iaid(
int ifindex,
const uint8_t *mac,
size_t mac_len,
const struct hw_addr_data *hw_addr,
bool legacy_unstable_byteorder,
bool use_mac,
void *ret);

View File

@@ -71,6 +71,7 @@ struct sd_dhcp6_client {
char **vendor_class;
OrderedHashmap *extra_options;
OrderedSet *vendor_options;
bool rapid_commit;
struct sd_dhcp6_lease *lease;

View File

@@ -510,7 +510,7 @@ int dhcp6_option_parse(
if (buflen < offsetof(DHCP6Option, data))
return -EBADMSG;
if (*offset >= buflen - offsetof(DHCP6Option, data))
if (*offset > buflen - offsetof(DHCP6Option, data))
return -EBADMSG;
len = unaligned_read_be16(buf + *offset + offsetof(DHCP6Option, len));
@@ -520,14 +520,14 @@ int dhcp6_option_parse(
*ret_option_code = unaligned_read_be16(buf + *offset + offsetof(DHCP6Option, code));
*ret_option_data_len = len;
*ret_option_data = buf + *offset + offsetof(DHCP6Option, data);
*ret_option_data = len == 0 ? NULL : buf + *offset + offsetof(DHCP6Option, data);
*offset += offsetof(DHCP6Option, data) + len;
return 0;
}
int dhcp6_option_parse_status(const uint8_t *data, size_t data_len, char **ret_status_message) {
assert(data);
assert(data || data_len == 0);
if (data_len < sizeof(uint16_t))
return -EBADMSG;
@@ -805,7 +805,7 @@ int dhcp6_option_parse_addresses(
struct in6_addr **addrs,
size_t *count) {
assert(optval);
assert(optval || optlen == 0);
assert(addrs);
assert(count);
@@ -828,8 +828,8 @@ static int parse_domain(const uint8_t **data, size_t *len, char **ret) {
int r;
assert(data);
assert(*data);
assert(len);
assert(*data || *len == 0);
assert(ret);
optval = *data;
@@ -893,7 +893,7 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, size_t optlen, char **r
_cleanup_free_ char *domain = NULL;
int r;
assert(optval);
assert(optval || optlen == 0);
assert(ret);
r = parse_domain(&optval, &optlen, &domain);
@@ -912,7 +912,7 @@ int dhcp6_option_parse_domainname_list(const uint8_t *optval, size_t optlen, cha
_cleanup_strv_free_ char **names = NULL;
int r;
assert(optval);
assert(optval || optlen == 0);
assert(ret);
if (optlen <= 1)

View File

@@ -122,9 +122,8 @@ int sd_dhcp6_client_set_mac(
return 0;
}
memcpy(client->hw_addr.bytes, addr, addr_len);
client->hw_addr.length = addr_len;
client->arp_type = arp_type;
hw_addr_set(&client->hw_addr, addr, addr_len);
return 0;
}
@@ -223,8 +222,8 @@ static int dhcp6_client_set_duid_internal(
} else {
#if 0 /* NM_IGNORED */
r = dhcp_identifier_set_duid(duid_type, client->hw_addr.bytes, client->hw_addr.length,
client->arp_type, llt_time, client->test_mode, &client->duid, &client->duid_len);
r = dhcp_identifier_set_duid(duid_type, &client->hw_addr, client->arp_type, llt_time,
client->test_mode, &client->duid, &client->duid_len);
if (r == -EOPNOTSUPP)
return log_dhcp6_client_errno(client, r,
"Failed to set %s. MAC address is not set or "
@@ -310,7 +309,7 @@ static int client_ensure_iaid(sd_dhcp6_client *client) {
if (client->iaid_set)
return 0;
r = dhcp_identifier_set_iaid(client->ifindex, client->hw_addr.bytes, client->hw_addr.length,
r = dhcp_identifier_set_iaid(client->ifindex, &client->hw_addr,
/* legacy_unstable_byteorder = */ true,
/* use_mac = */ client->test_mode,
&iaid);
@@ -501,6 +500,14 @@ int dhcp6_client_set_transaction_id(sd_dhcp6_client *client, uint32_t transactio
return 0;
}
int sd_dhcp6_client_set_rapid_commit(sd_dhcp6_client *client, int enable) {
assert_return(client, -EINVAL);
assert_return(!sd_dhcp6_client_is_running(client), -EBUSY);
client->rapid_commit = enable;
return 0;
}
int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) {
assert_return(client, -EINVAL);
@@ -724,9 +731,11 @@ int dhcp6_client_send_message(sd_dhcp6_client *client) {
break;
case DHCP6_STATE_SOLICITATION:
r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
if (r < 0)
return r;
if (client->rapid_commit) {
r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
if (r < 0)
return r;
}
r = client_append_common_options_in_managed_mode(client, &opt, &optlen,
&client->ia_na, &client->ia_pd);
@@ -1170,6 +1179,10 @@ static int client_process_advertise_or_rapid_commit_reply(
if (message->type == DHCP6_MESSAGE_REPLY) {
bool rapid_commit;
if (!client->rapid_commit)
return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
"Received unexpected reply message, even we sent a solicit message without the rapid commit option, ignoring.");
r = dhcp6_lease_get_rapid_commit(lease, &rapid_commit);
if (r < 0)
return r;
@@ -1477,6 +1490,7 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
.ifindex = -1,
.request_ia = DHCP6_REQUEST_IA_NA | DHCP6_REQUEST_IA_PD,
.fd = -1,
.rapid_commit = true,
};
*ret = TAKE_PTR(client);

View File

@@ -469,7 +469,9 @@ static int dhcp6_lease_parse_message(
r = dhcp6_option_parse(message->options, len, &offset, &optcode, &optlen, &optval);
if (r < 0)
return r;
return log_dhcp6_client_errno(client, r,
"Failed to parse option header at offset %zu of total length %zu: %m",
offset, len);
switch (optcode) {
case SD_DHCP6_OPTION_CLIENTID:
@@ -479,7 +481,7 @@ static int dhcp6_lease_parse_message(
r = dhcp6_lease_set_clientid(lease, optval, optlen);
if (r < 0)
return r;
return log_dhcp6_client_errno(client, r, "Failed to set client ID: %m");
break;
@@ -490,17 +492,17 @@ static int dhcp6_lease_parse_message(
r = dhcp6_lease_set_serverid(lease, optval, optlen);
if (r < 0)
return r;
return log_dhcp6_client_errno(client, r, "Failed to set server ID: %m");
break;
case SD_DHCP6_OPTION_PREFERENCE:
if (optlen != 1)
return -EINVAL;
return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "Received invalid length for preference.");
r = dhcp6_lease_set_preference(lease, optval[0]);
if (r < 0)
return r;
return log_dhcp6_client_errno(client, r, "Failed to set preference: %m");
break;
@@ -509,7 +511,7 @@ static int dhcp6_lease_parse_message(
r = dhcp6_option_parse_status(optval, optlen, &msg);
if (r < 0)
return r;
return log_dhcp6_client_errno(client, r, "Failed to parse status code: %m");
if (r > 0)
return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
@@ -529,9 +531,11 @@ static int dhcp6_lease_parse_message(
r = dhcp6_option_parse_ia(client, client->ia_na.header.id, optcode, optlen, optval, &ia);
if (r == -ENOMEM)
return r;
if (r < 0)
return log_oom_debug();
if (r < 0) {
log_dhcp6_client_errno(client, r, "Failed to parse IA_NA option, ignoring: %m");
continue;
}
if (lease->ia_na) {
log_dhcp6_client(client, "Received duplicate matching IA_NA option, ignoring.");
@@ -552,9 +556,11 @@ static int dhcp6_lease_parse_message(
r = dhcp6_option_parse_ia(client, client->ia_pd.header.id, optcode, optlen, optval, &ia);
if (r == -ENOMEM)
return r;
if (r < 0)
return log_oom_debug();
if (r < 0) {
log_dhcp6_client_errno(client, r, "Failed to parse IA_PD option, ignoring: %m");
continue;
}
if (lease->ia_pd) {
log_dhcp6_client(client, "Received duplicate matching IA_PD option, ignoring.");
@@ -566,9 +572,12 @@ static int dhcp6_lease_parse_message(
break;
}
case SD_DHCP6_OPTION_RAPID_COMMIT:
if (optlen != 0)
log_dhcp6_client(client, "Received rapid commit option with an invalid length (%zu), ignoring.", optlen);
r = dhcp6_lease_set_rapid_commit(lease);
if (r < 0)
return r;
return log_dhcp6_client_errno(client, r, "Failed to set rapid commit flag: %m");
break;
@@ -609,7 +618,8 @@ static int dhcp6_lease_parse_message(
case SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME:
if (optlen != 4)
return -EINVAL;
return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
"Received information refresh time option with an invalid length (%zu).", optlen);
irt = unaligned_read_be32((be32_t *) optval) * USEC_PER_SEC;
break;

View File

@@ -51,19 +51,19 @@ static bool event_source_is_offline(sd_event_source *s) {
}
static const char* const event_source_type_table[_SOURCE_EVENT_SOURCE_TYPE_MAX] = {
[SOURCE_IO] = "io",
[SOURCE_TIME_REALTIME] = "realtime",
[SOURCE_TIME_BOOTTIME] = "bootime",
[SOURCE_TIME_MONOTONIC] = "monotonic",
[SOURCE_IO] = "io",
[SOURCE_TIME_REALTIME] = "realtime",
[SOURCE_TIME_BOOTTIME] = "bootime",
[SOURCE_TIME_MONOTONIC] = "monotonic",
[SOURCE_TIME_REALTIME_ALARM] = "realtime-alarm",
[SOURCE_TIME_BOOTTIME_ALARM] = "boottime-alarm",
[SOURCE_SIGNAL] = "signal",
[SOURCE_CHILD] = "child",
[SOURCE_DEFER] = "defer",
[SOURCE_POST] = "post",
[SOURCE_EXIT] = "exit",
[SOURCE_WATCHDOG] = "watchdog",
[SOURCE_INOTIFY] = "inotify",
[SOURCE_SIGNAL] = "signal",
[SOURCE_CHILD] = "child",
[SOURCE_DEFER] = "defer",
[SOURCE_POST] = "post",
[SOURCE_EXIT] = "exit",
[SOURCE_WATCHDOG] = "watchdog",
[SOURCE_INOTIFY] = "inotify",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(event_source_type, int);
@@ -126,10 +126,10 @@ struct sd_event {
Hashmap *inotify_data; /* indexed by priority */
/* A list of inode structures that still have an fd open, that we need to close before the next loop iteration */
LIST_HEAD(struct inode_data, inode_data_to_close);
LIST_HEAD(struct inode_data, inode_data_to_close_list);
/* A list of inotify objects that already have events buffered which aren't processed yet */
LIST_HEAD(struct inotify_data, inotify_data_buffered);
LIST_HEAD(struct inotify_data, buffered_inotify_data_list);
pid_t original_pid;
@@ -422,6 +422,8 @@ fail:
}
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_event, sd_event, event_free);
#define PROTECT_EVENT(e) \
_unused_ _cleanup_(sd_event_unrefp) sd_event *_ref = sd_event_ref(e);
_public_ sd_event_source* sd_event_source_disable_unref(sd_event_source *s) {
if (s)
@@ -1696,7 +1698,7 @@ static void event_free_inotify_data(sd_event *e, struct inotify_data *d) {
assert(hashmap_isempty(d->wd));
if (d->buffer_filled > 0)
LIST_REMOVE(buffered, e->inotify_data_buffered, d);
LIST_REMOVE(buffered, e->buffered_inotify_data_list, d);
hashmap_free(d->inodes);
hashmap_free(d->wd);
@@ -1805,10 +1807,10 @@ static void event_free_inode_data(
if (!d)
return;
assert(LIST_IS_EMPTY(d->event_sources));
assert(!d->event_sources);
if (d->fd >= 0) {
LIST_REMOVE(to_close, e->inode_data_to_close, d);
LIST_REMOVE(to_close, e->inode_data_to_close_list, d);
safe_close(d->fd);
}
@@ -1868,7 +1870,7 @@ static void event_gc_inode_data(
if (!d)
return;
if (!LIST_IS_EMPTY(d->event_sources))
if (d->event_sources)
return;
inotify_data = d->inotify_data;
@@ -2070,7 +2072,7 @@ static int event_add_inotify_fd_internal(
}
}
LIST_PREPEND(to_close, e->inode_data_to_close, inode_data);
LIST_PREPEND(to_close, e->inode_data_to_close_list, inode_data);
}
/* Link our event source to the inode data object */
@@ -2143,12 +2145,9 @@ static sd_event_source* event_source_free(sd_event_source *s) {
* we still retain a valid event source object after
* the callback. */
if (s->dispatching) {
if (s->type == SOURCE_IO)
source_io_unregister(s);
if (s->dispatching)
source_disconnect(s);
} else
else
source_free(s);
return NULL;
@@ -2357,7 +2356,7 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority)
goto fail;
}
LIST_PREPEND(to_close, s->event->inode_data_to_close, new_inode_data);
LIST_PREPEND(to_close, s->event->inode_data_to_close_list, new_inode_data);
}
/* Move the event source to the new inode data structure */
@@ -3423,7 +3422,7 @@ static int event_inotify_data_read(sd_event *e, struct inotify_data *d, uint32_t
assert(n > 0);
d->buffer_filled = (size_t) n;
LIST_PREPEND(buffered, e->inotify_data_buffered, d);
LIST_PREPEND(buffered, e->buffered_inotify_data_list, d);
return 1;
}
@@ -3441,7 +3440,7 @@ static void event_inotify_data_drop(sd_event *e, struct inotify_data *d, size_t
d->buffer_filled -= sz;
if (d->buffer_filled == 0)
LIST_REMOVE(buffered, e->inotify_data_buffered, d);
LIST_REMOVE(buffered, e->buffered_inotify_data_list, d);
}
static int event_inotify_data_process(sd_event *e, struct inotify_data *d) {
@@ -3534,7 +3533,7 @@ static int process_inotify(sd_event *e) {
assert(e);
LIST_FOREACH(buffered, d, e->inotify_data_buffered) {
LIST_FOREACH(buffered, d, e->buffered_inotify_data_list) {
r = event_inotify_data_process(e, d);
if (r < 0)
return r;
@@ -3546,8 +3545,8 @@ static int process_inotify(sd_event *e) {
}
static int source_dispatch(sd_event_source *s) {
_cleanup_(sd_event_unrefp) sd_event *saved_event = NULL;
EventSourceType saved_type;
sd_event *saved_event;
int r = 0;
assert(s);
@@ -3559,7 +3558,8 @@ static int source_dispatch(sd_event_source *s) {
/* Similarly, store a reference to the event loop object, so that we can still access it after the
* callback might have invalidated/disconnected the event source. */
saved_event = sd_event_ref(s->event);
saved_event = s->event;
PROTECT_EVENT(saved_event);
/* Check if we hit the ratelimit for this event source, and if so, let's disable it. */
assert(!s->ratelimited);
@@ -3760,7 +3760,7 @@ static int dispatch_exit(sd_event *e) {
return 0;
}
_unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
PROTECT_EVENT(e);
e->iteration++;
e->state = SD_EVENT_EXITING;
r = source_dispatch(p);
@@ -3831,11 +3831,11 @@ static void event_close_inode_data_fds(sd_event *e) {
* for the inode). Hence, let's close them when entering the first iteration after they were added, as a
* compromise. */
while ((d = e->inode_data_to_close)) {
while ((d = e->inode_data_to_close_list)) {
assert(d->fd >= 0);
d->fd = safe_close(d->fd);
LIST_REMOVE(to_close, e->inode_data_to_close, d);
LIST_REMOVE(to_close, e->inode_data_to_close_list, d);
}
}
@@ -3854,7 +3854,7 @@ _public_ int sd_event_prepare(sd_event *e) {
assert_return(!e->default_event_ptr || e->tid == gettid(), -EREMOTEIO);
/* Make sure that none of the preparation callbacks ends up freeing the event source under our feet */
_unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
PROTECT_EVENT(e);
if (e->exit_requested)
goto pending;
@@ -3889,7 +3889,7 @@ _public_ int sd_event_prepare(sd_event *e) {
event_close_inode_data_fds(e);
if (event_next_pending(e) || e->need_process_child || !LIST_IS_EMPTY(e->inotify_data_buffered))
if (event_next_pending(e) || e->need_process_child || e->buffered_inotify_data_list)
goto pending;
e->state = SD_EVENT_ARMED;
@@ -3969,7 +3969,7 @@ static int process_epoll(sd_event *e, usec_t timeout, int64_t threshold, int64_t
n_event_max = MALLOC_ELEMENTSOF(e->event_queue);
/* If we still have inotify data buffered, then query the other fds, but don't wait on it */
if (!LIST_IS_EMPTY(e->inotify_data_buffered))
if (e->buffered_inotify_data_list)
timeout = 0;
for (;;) {
@@ -4184,7 +4184,7 @@ _public_ int sd_event_dispatch(sd_event *e) {
p = event_next_pending(e);
if (p) {
_unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
PROTECT_EVENT(e);
e->state = SD_EVENT_RUNNING;
r = source_dispatch(p);
@@ -4236,7 +4236,7 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) {
}
/* Make sure that none of the preparation callbacks ends up freeing the event source under our feet */
_unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
PROTECT_EVENT(e);
r = sd_event_prepare(e);
if (r == 0)
@@ -4266,7 +4266,7 @@ _public_ int sd_event_loop(sd_event *e) {
assert_return(!event_pid_changed(e), -ECHILD);
assert_return(e->state == SD_EVENT_INITIAL, -EBUSY);
_unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
PROTECT_EVENT(e);
while (e->state != SD_EVENT_FINISHED) {
r = sd_event_run(e, UINT64_MAX);

View File

@@ -85,7 +85,7 @@ typedef void (*_sd_destroy_t)(void *userdata);
#endif
#ifndef _SD_ARRAY_STATIC
# if __STDC_VERSION__ >= 199901L
# if __STDC_VERSION__ >= 199901L && !defined(__cplusplus)
# define _SD_ARRAY_STATIC static
# else
# define _SD_ARRAY_STATIC

View File

@@ -262,6 +262,7 @@ int sd_dhcp6_client_set_address_request(sd_dhcp6_client *client,
int request);
int sd_dhcp6_client_add_vendor_option(sd_dhcp6_client *client,
sd_dhcp6_option *v);
int sd_dhcp6_client_set_rapid_commit(sd_dhcp6_client *client, int enable);
int sd_dhcp6_client_get_lease(
sd_dhcp6_client *client,

View File

@@ -51,6 +51,8 @@
#define LOG_TRACE 0
#define WANT_LINUX_FS_H 0
#define BUILD_MODE_DEVELOPER (NM_MORE_ASSERTS > 0)
#define LOG_MESSAGE_VERIFICATION (NM_MORE_ASSERTS > 0)

View File

@@ -50,16 +50,30 @@ typedef void* (*mfree_func_t)(void *p);
#define malloc0(n) (calloc(1, (n) ?: 1))
#define free_and_replace(a, b) \
#define free_and_replace_full(a, b, free_func) \
({ \
typeof(a)* _a = &(a); \
typeof(b)* _b = &(b); \
free(*_a); \
free_func(*_a); \
*_a = *_b; \
*_b = NULL; \
0; \
})
#define free_and_replace(a, b) \
free_and_replace_full(a, b, free)
/* This is similar to free_and_replace_full(), but NULL is not assigned to 'b', and its reference counter is
* increased. */
#define unref_and_replace_full(a, b, ref_func, unref_func) \
({ \
typeof(a)* _a = &(a); \
typeof(b) _b = ref_func(b); \
unref_func(*_a); \
*_a = _b; \
0; \
})
void* memdup(const void *p, size_t l) _alloc_(2);
void* memdup_suffix0(const void *p, size_t l); /* We can't use _alloc_() here, since we return a buffer one byte larger than the specified size */

View File

@@ -35,6 +35,15 @@ char *hw_addr_to_string_full(
return buffer;
}
struct hw_addr_data *hw_addr_set(struct hw_addr_data *addr, const uint8_t *bytes, size_t length) {
assert(addr);
assert(length <= HW_ADDR_MAX_SIZE);
addr->length = length;
memcpy_safe(addr->bytes, bytes, length);
return addr;
}
int hw_addr_compare(const struct hw_addr_data *a, const struct hw_addr_data *b) {
int r;

View File

@@ -52,6 +52,8 @@ static inline char *hw_addr_to_string(const struct hw_addr_data *addr, char buff
#define HW_ADDR_NULL ((const struct hw_addr_data){})
struct hw_addr_data *hw_addr_set(struct hw_addr_data *addr, const uint8_t *bytes, size_t length);
void hw_addr_hash_func(const struct hw_addr_data *p, struct siphash *state);
int hw_addr_compare(const struct hw_addr_data *a, const struct hw_addr_data *b);
static inline bool hw_addr_equal(const struct hw_addr_data *a, const struct hw_addr_data *b) {

View File

@@ -5,7 +5,9 @@
#include <errno.h>
#include <fcntl.h>
#include <linux/btrfs.h>
#if WANT_LINUX_FS_H
#include <linux/fs.h>
#endif
#include <linux/magic.h>
#include <sys/ioctl.h>
#include <sys/resource.h>

View File

@@ -6,6 +6,7 @@
#include "hash-funcs.h"
#include "path-util.h"
#include "strv.h"
void string_hash_func(const char *p, struct siphash *state) {
siphash24_compress(p, strlen(p) + 1, state);
@@ -17,6 +18,9 @@ DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(string_hash_ops_free,
DEFINE_HASH_OPS_FULL(string_hash_ops_free_free,
char, string_hash_func, string_compare_func, free,
void, free);
DEFINE_HASH_OPS_FULL(string_hash_ops_free_strv_free,
char, string_hash_func, string_compare_func, free,
char*, strv_free);
#if 0 /* NM_IGNORED */
void path_hash_func(const char *q, struct siphash *state) {

View File

@@ -78,6 +78,7 @@ void string_hash_func(const char *p, struct siphash *state);
extern const struct hash_ops string_hash_ops;
extern const struct hash_ops string_hash_ops_free;
extern const struct hash_ops string_hash_ops_free_free;
extern const struct hash_ops string_hash_ops_free_strv_free;
void path_hash_func(const char *p, struct siphash *state);
extern const struct hash_ops path_hash_ops;

View File

@@ -90,12 +90,7 @@ OrderedHashmap* _ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DE
#define ordered_hashmap_new(ops) _ordered_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS)
#define hashmap_free_and_replace(a, b) \
({ \
hashmap_free(a); \
(a) = (b); \
(b) = NULL; \
0; \
})
free_and_replace_full(a, b, hashmap_free)
HashmapBase* _hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value);
static inline Hashmap* hashmap_free(Hashmap *h) {

View File

@@ -51,6 +51,20 @@ bool in4_addr_is_link_local(const struct in_addr *a) {
return (be32toh(a->s_addr) & UINT32_C(0xFFFF0000)) == (UINT32_C(169) << 24 | UINT32_C(254) << 16);
}
bool in4_addr_is_link_local_dynamic(const struct in_addr *a) {
assert(a);
if (!in4_addr_is_link_local(a))
return false;
/* 169.254.0.0/24 and 169.254.255.0/24 must not be used for the dynamic IPv4LL assignment.
* See RFC 3927 Section 2.1:
* The IPv4 prefix 169.254/16 is registered with the IANA for this purpose. The first 256 and last
* 256 addresses in the 169.254/16 prefix are reserved for future use and MUST NOT be selected by a
* host using this dynamic configuration mechanism. */
return !IN_SET(be32toh(a->s_addr) & 0x0000FF00U, 0x0000U, 0xFF00U);
}
bool in6_addr_is_link_local(const struct in6_addr *a) {
assert(a);

View File

@@ -44,6 +44,7 @@ static inline bool in_addr_data_is_set(const struct in_addr_data *a) {
int in_addr_is_multicast(int family, const union in_addr_union *u);
bool in4_addr_is_link_local(const struct in_addr *a);
bool in4_addr_is_link_local_dynamic(const struct in_addr *a);
bool in6_addr_is_link_local(const struct in6_addr *a);
int in_addr_is_link_local(int family, const union in_addr_union *u);
bool in6_addr_is_link_local_all_nodes(const struct in6_addr *a);

View File

@@ -170,9 +170,6 @@
i != (p); \
i = i->name##_next ? i->name##_next : (head))
#define LIST_IS_EMPTY(head) \
(!(head))
/* Join two lists tail to head: a->b, c->d to a->b->c->d and de-initialise second list */
#define LIST_JOIN(name,a,b) \
do { \

View File

@@ -88,10 +88,6 @@
_Pragma("GCC diagnostic push")
#endif
#define DISABLE_WARNING_FLOAT_EQUAL \
_Pragma("GCC diagnostic push"); \
_Pragma("GCC diagnostic ignored \"-Wfloat-equal\"")
#define DISABLE_WARNING_TYPE_LIMITS \
_Pragma("GCC diagnostic push"); \
_Pragma("GCC diagnostic ignored \"-Wtype-limits\"")

View File

@@ -1061,7 +1061,7 @@ int path_extract_filename(const char *path, char **ret) {
return -ENOMEM;
*ret = TAKE_PTR(a);
return strlen(c) > (size_t)r ? O_DIRECTORY : 0;
return strlen(c) > (size_t) r ? O_DIRECTORY : 0;
}
int path_extract_directory(const char *path, char **ret) {
@@ -1115,7 +1115,7 @@ bool filename_is_valid(const char *p) {
if (isempty(p))
return false;
if (dot_or_dot_dot(p))
if (dot_or_dot_dot(p)) /* Yes, in this context we consider "." and ".." invalid */
return false;
e = strchrnul(p, '/');

View File

@@ -45,12 +45,16 @@
#endif
static inline bool is_path(const char *p) {
assert(p);
if (!p) /* A NULL pointer is definitely not a path */
return false;
return strchr(p, '/');
}
static inline bool path_is_absolute(const char *p) {
assert(p);
if (!p) /* A NULL pointer is definitely not an absolute path */
return false;
return p[0] == '/';
}
@@ -159,10 +163,10 @@ int path_extract_directory(const char *path, char **ret);
bool filename_is_valid(const char *p) _pure_;
bool path_is_valid_full(const char *p, bool accept_dot_dot) _pure_;
static inline bool path_is_valid(const char *p) {
return path_is_valid_full(p, true);
return path_is_valid_full(p, /* accept_dot_dot= */ true);
}
static inline bool path_is_safe(const char *p) {
return path_is_valid_full(p, false);
return path_is_valid_full(p, /* accept_dot_dot= */ false);
}
bool path_is_normalized(const char *p) _pure_;

View File

@@ -1156,7 +1156,7 @@ void reset_cached_pid(void) {
pid_t getpid_cached(void) {
static bool installed = false;
pid_t current_value;
pid_t current_value = CACHED_PID_UNSET;
/* getpid_cached() is much like getpid(), but caches the value in local memory, to avoid having to invoke a
* system call each time. This restores glibc behaviour from before 2.24, when getpid() was unconditionally
@@ -1167,7 +1167,13 @@ pid_t getpid_cached(void) {
* https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=c579f48edba88380635ab98cb612030e3ed8691e
*/
current_value = __sync_val_compare_and_swap(&cached_pid, CACHED_PID_UNSET, CACHED_PID_BUSY);
__atomic_compare_exchange_n(
&cached_pid,
&current_value,
CACHED_PID_BUSY,
false,
__ATOMIC_SEQ_CST,
__ATOMIC_SEQ_CST);
switch (current_value) {
@@ -1589,6 +1595,30 @@ bool invoked_as(char *argv[], const char *token) {
return strstr(last_path_component(argv[0]), token);
}
bool invoked_by_systemd(void) {
int r;
/* If the process is directly executed by PID1 (e.g. ExecStart= or generator), systemd-importd,
* or systemd-homed, then $SYSTEMD_EXEC_PID= is set, and read the command line. */
const char *e = getenv("SYSTEMD_EXEC_PID");
if (!e)
return false;
if (streq(e, "*"))
/* For testing. */
return true;
pid_t p;
r = parse_pid(e, &p);
if (r < 0) {
/* We know that systemd sets the variable correctly. Something else must have set it. */
log_debug_errno(r, "Failed to parse \"SYSTEMD_EXEC_PID=%s\", ignoring: %m", e);
return false;
}
return getpid_cached() == p;
}
_noreturn_ void freeze(void) {
log_close();

View File

@@ -192,6 +192,8 @@ int setpriority_closest(int priority);
bool invoked_as(char *argv[], const char *token);
bool invoked_by_systemd(void);
_noreturn_ void freeze(void);
bool argv_looks_like_help(int argc, char **argv);

View File

@@ -6,12 +6,7 @@
#include "macro.h"
#define set_free_and_replace(a, b) \
({ \
set_free(a); \
(a) = (b); \
(b) = NULL; \
0; \
})
free_and_replace_full(a, b, set_free)
Set* _set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
#define set_new(ops) _set_new(ops HASHMAP_DEBUG_SRC_ARGS)

View File

@@ -39,16 +39,17 @@ int is_symlink(const char *path) {
}
#endif /* NM_IGNORED */
int is_dir(const char* path, bool follow) {
int is_dir_full(int atfd, const char* path, bool follow) {
struct stat st;
int r;
assert(path);
assert(atfd >= 0 || atfd == AT_FDCWD);
assert(atfd >= 0 || path);
if (follow)
r = stat(path, &st);
if (path)
r = fstatat(atfd, path, &st, follow ? 0 : AT_SYMLINK_NOFOLLOW);
else
r = lstat(path, &st);
r = fstat(atfd, &st);
if (r < 0)
return -errno;
@@ -56,15 +57,6 @@ int is_dir(const char* path, bool follow) {
}
#if 0 /* NM_IGNORED */
int is_dir_fd(int fd) {
struct stat st;
if (fstat(fd, &st) < 0)
return -errno;
return !!S_ISDIR(st.st_mode);
}
int is_device_node(const char *path) {
struct stat info;

View File

@@ -13,8 +13,13 @@
#include "missing_stat.h"
int is_symlink(const char *path);
int is_dir(const char *path, bool follow);
int is_dir_fd(int fd);
int is_dir_full(int atfd, const char *fname, bool follow);
static inline int is_dir(const char *path, bool follow) {
return is_dir_full(AT_FDCWD, path, follow);
}
static inline int is_dir_fd(int fd) {
return is_dir_full(fd, NULL, false);
}
int is_device_node(const char *path);
int dir_is_empty_at(int dir_fd, const char *path, bool ignore_hidden_or_backup);

View File

@@ -258,14 +258,7 @@ int strv_extend_n(char ***l, const char *value, size_t n);
int fputstrv(FILE *f, char * const *l, const char *separator, bool *space);
#define strv_free_and_replace(a, b) \
({ \
char ***_a = &(a); \
char ***_b = &(b); \
strv_free(*_a); \
(*_a) = (*_b); \
(*_b) = NULL; \
0; \
})
free_and_replace_full(a, b, strv_free)
extern const struct hash_ops string_strv_hash_ops;
int _string_strv_hashmap_put(Hashmap **h, const char *key, const char *value HASHMAP_DEBUG_PARAMS);

View File

@@ -595,7 +595,7 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
t = b;
}
n = MIN((size_t) k, l);
n = MIN((size_t) k, l-1);
l -= n;
p += n;

View File

@@ -95,6 +95,20 @@
_expr_; \
})
#define ASSERT_NONNEG(expr) \
({ \
typeof(expr) _expr_ = (expr), _zero = 0; \
assert(_expr_ >= _zero); \
_expr_; \
})
#define ASSERT_SE_NONNEG(expr) \
({ \
typeof(expr) _expr_ = (expr), _zero = 0; \
assert_se(_expr_ >= _zero); \
_expr_; \
})
#define assert_cc(expr) static_assert(expr, #expr)
@@ -106,10 +120,10 @@
* on this macro will run concurrently to all other code conditionalized
* the same way, there's no ordering or completion enforced. */
#define ONCE __ONCE(UNIQ_T(_once_, UNIQ))
#define __ONCE(o) \
({ \
static bool (o) = false; \
__sync_bool_compare_and_swap(&(o), false, true); \
#define __ONCE(o) \
({ \
static bool (o) = false; \
__atomic_exchange_n(&(o), true, __ATOMIC_SEQ_CST); \
})
#undef MAX
@@ -186,6 +200,27 @@
MIN(_c, z); \
})
/* Returns true if the passed integer is a positive power of two */
#define CONST_ISPOWEROF2(x) \
((x) > 0 && ((x) & ((x) - 1)) == 0)
#if 0 /* NM_IGNORED */
#define ISPOWEROF2(x) \
__builtin_choose_expr( \
__builtin_constant_p(x), \
CONST_ISPOWEROF2(x), \
({ \
const typeof(x) _x = (x); \
CONST_ISPOWEROF2(_x); \
}))
#else /* NM_IGNORED */
#define ISPOWEROF2(x) \
({ \
const typeof(x) _x = (x); \
CONST_ISPOWEROF2(_x); \
})
#endif /* NM_IGNORED */
#define LESS_BY(a, b) __LESS_BY(UNIQ, (a), UNIQ, (b))
#define __LESS_BY(aq, a, bq, b) \
({ \
@@ -300,16 +335,7 @@
})
static inline size_t ALIGN_TO(size_t l, size_t ali) {
/* Check that alignment is exponent of 2 */
#if SIZE_MAX == UINT_MAX
assert(__builtin_popcount(ali) == 1);
#elif SIZE_MAX == ULONG_MAX
assert(__builtin_popcountl(ali) == 1);
#elif SIZE_MAX == ULLONG_MAX
assert(__builtin_popcountll(ali) == 1);
#else
#error "Unexpected size_t"
#endif
assert(ISPOWEROF2(ali));
if (l > SIZE_MAX - (ali - 1))
return SIZE_MAX; /* indicate overflow */
@@ -330,7 +356,7 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
__builtin_choose_expr( \
__builtin_constant_p(l) && \
__builtin_constant_p(ali) && \
__builtin_popcountll(ali) == 1 && /* is power of 2? */ \
CONST_ISPOWEROF2(ali) && \
(l <= SIZE_MAX - (ali - 1)), /* overflow? */ \
((l) + (ali) - 1) & ~((ali) - 1), \
VOID_0)