1
0
mirror of https://github.com/systemd/systemd synced 2026-04-10 09:04:50 +02:00

Compare commits

..

No commits in common. "f836390fa75f055b30867a81883075c4d791e7fd" and "de1253e4c63dbc683177f63c9b41e41dfe097cba" have entirely different histories.

14 changed files with 315 additions and 431 deletions

View File

@ -38,14 +38,14 @@ jobs:
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Initialize CodeQL
uses: github/codeql-action/init@546b30f35ae5a3db0e0be1843008c2224f71c3b0
uses: github/codeql-action/init@e095058bfa09de8070f94e98f5dc059531bc6235
with:
languages: ${{ matrix.language }}
- run: sudo -E .github/workflows/unit_tests.sh SETUP
- name: Autobuild
uses: github/codeql-action/autobuild@546b30f35ae5a3db0e0be1843008c2224f71c3b0
uses: github/codeql-action/autobuild@e095058bfa09de8070f94e98f5dc059531bc6235
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@546b30f35ae5a3db0e0be1843008c2224f71c3b0
uses: github/codeql-action/analyze@e095058bfa09de8070f94e98f5dc059531bc6235

View File

@ -982,7 +982,7 @@ static int list_dependencies_one(sd_bus *bus, const char *name, unsigned level,
return r;
STRV_FOREACH(c, deps) {
times = hashmap_get(unit_times_hashmap, *c); /* lgtm [cpp/inconsistent-null-check] */
times = hashmap_get(unit_times_hashmap, *c);
if (times_in_range(times, boot) && times->activated >= service_longest)
service_longest = times->activated;
}
@ -991,7 +991,7 @@ static int list_dependencies_one(sd_bus *bus, const char *name, unsigned level,
return r;
STRV_FOREACH(c, deps) {
times = hashmap_get(unit_times_hashmap, *c); /* lgtm [cpp/inconsistent-null-check] */
times = hashmap_get(unit_times_hashmap, *c);
if (times_in_range(times, boot) && service_longest - times->activated <= arg_fuzz)
to_print++;
}
@ -1000,7 +1000,7 @@ static int list_dependencies_one(sd_bus *bus, const char *name, unsigned level,
return r;
STRV_FOREACH(c, deps) {
times = hashmap_get(unit_times_hashmap, *c); /* lgtm [cpp/inconsistent-null-check] */
times = hashmap_get(unit_times_hashmap, *c);
if (!times_in_range(times, boot) || service_longest - times->activated > arg_fuzz)
continue;

View File

@ -181,13 +181,13 @@ static int get_process_cmdline_nulstr(
return r;
}
int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret) {
int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **line) {
_cleanup_free_ char *t = NULL;
size_t k;
char *ans;
assert(line);
assert(pid >= 0);
assert(ret);
/* Retrieve and format a commandline. See above for discussion of retrieval options.
*
@ -214,17 +214,11 @@ int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags
assert(!(flags & PROCESS_CMDLINE_USE_LOCALE));
_cleanup_strv_free_ char **args = NULL;
char **p;
args = strv_parse_nulstr(t, k);
if (!args)
return -ENOMEM;
/* Drop trailing empty strings. See issue #21186. */
STRV_FOREACH_BACKWARDS(p, args)
if (isempty(*p))
*p = mfree(*p);
ans = quote_command_line(args, shflags);
if (!ans)
return -ENOMEM;
@ -246,7 +240,7 @@ int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags
ans = str_realloc(ans);
}
*ret = ans;
*line = ans;
return 0;
}
@ -453,29 +447,29 @@ int is_kernel_thread(pid_t pid) {
return !!(flags & PF_KTHREAD);
}
int get_process_capeff(pid_t pid, char **ret) {
int get_process_capeff(pid_t pid, char **capeff) {
const char *p;
int r;
assert(capeff);
assert(pid >= 0);
assert(ret);
p = procfs_file_alloca(pid, "status");
r = get_proc_field(p, "CapEff", WHITESPACE, ret);
r = get_proc_field(p, "CapEff", WHITESPACE, capeff);
if (r == -ENOENT)
return -ESRCH;
return r;
}
static int get_process_link_contents(const char *proc_file, char **ret) {
static int get_process_link_contents(const char *proc_file, char **name) {
int r;
assert(proc_file);
assert(ret);
assert(name);
r = readlink_malloc(proc_file, ret);
r = readlink_malloc(proc_file, name);
if (r == -ENOENT)
return -ESRCH;
if (r < 0)
@ -484,33 +478,32 @@ static int get_process_link_contents(const char *proc_file, char **ret) {
return 0;
}
int get_process_exe(pid_t pid, char **ret) {
int get_process_exe(pid_t pid, char **name) {
const char *p;
char *d;
int r;
assert(pid >= 0);
assert(ret);
p = procfs_file_alloca(pid, "exe");
r = get_process_link_contents(p, ret);
r = get_process_link_contents(p, name);
if (r < 0)
return r;
d = endswith(*ret, " (deleted)");
d = endswith(*name, " (deleted)");
if (d)
*d = '\0';
return 0;
}
static int get_process_id(pid_t pid, const char *field, uid_t *ret) {
static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
_cleanup_fclose_ FILE *f = NULL;
const char *p;
int r;
assert(field);
assert(ret);
assert(uid);
if (pid < 0)
return -EINVAL;
@ -540,62 +533,60 @@ static int get_process_id(pid_t pid, const char *field, uid_t *ret) {
l[strcspn(l, WHITESPACE)] = 0;
return parse_uid(l, ret);
return parse_uid(l, uid);
}
}
return -EIO;
}
int get_process_uid(pid_t pid, uid_t *ret) {
int get_process_uid(pid_t pid, uid_t *uid) {
if (pid == 0 || pid == getpid_cached()) {
*ret = getuid();
*uid = getuid();
return 0;
}
return get_process_id(pid, "Uid:", ret);
return get_process_id(pid, "Uid:", uid);
}
int get_process_gid(pid_t pid, gid_t *ret) {
int get_process_gid(pid_t pid, gid_t *gid) {
if (pid == 0 || pid == getpid_cached()) {
*ret = getgid();
*gid = getgid();
return 0;
}
assert_cc(sizeof(uid_t) == sizeof(gid_t));
return get_process_id(pid, "Gid:", ret);
return get_process_id(pid, "Gid:", gid);
}
int get_process_cwd(pid_t pid, char **ret) {
int get_process_cwd(pid_t pid, char **cwd) {
const char *p;
assert(pid >= 0);
assert(ret);
if (pid == 0 || pid == getpid_cached())
return safe_getcwd(ret);
return safe_getcwd(cwd);
p = procfs_file_alloca(pid, "cwd");
return get_process_link_contents(p, ret);
return get_process_link_contents(p, cwd);
}
int get_process_root(pid_t pid, char **ret) {
int get_process_root(pid_t pid, char **root) {
const char *p;
assert(pid >= 0);
assert(ret);
p = procfs_file_alloca(pid, "root");
return get_process_link_contents(p, ret);
return get_process_link_contents(p, root);
}
#define ENVIRONMENT_BLOCK_MAX (5U*1024U*1024U)
int get_process_environ(pid_t pid, char **ret) {
int get_process_environ(pid_t pid, char **env) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *outcome = NULL;
size_t sz = 0;
@ -603,7 +594,7 @@ int get_process_environ(pid_t pid, char **ret) {
int r;
assert(pid >= 0);
assert(ret);
assert(env);
p = procfs_file_alloca(pid, "environ");
@ -635,7 +626,7 @@ int get_process_environ(pid_t pid, char **ret) {
}
outcome[sz] = '\0';
*ret = TAKE_PTR(outcome);
*env = TAKE_PTR(outcome);
return 0;
}
@ -694,13 +685,13 @@ int get_process_ppid(pid_t pid, pid_t *ret) {
return 0;
}
int get_process_umask(pid_t pid, mode_t *ret) {
int get_process_umask(pid_t pid, mode_t *umask) {
_cleanup_free_ char *m = NULL;
const char *p;
int r;
assert(umask);
assert(pid >= 0);
assert(ret);
p = procfs_file_alloca(pid, "status");
@ -708,7 +699,7 @@ int get_process_umask(pid_t pid, mode_t *ret) {
if (r == -ENOENT)
return -ESRCH;
return parse_mode(m, ret);
return parse_mode(m, umask);
}
int wait_for_terminate(pid_t pid, siginfo_t *status) {

View File

@ -38,17 +38,17 @@ typedef enum ProcessCmdlineFlags {
PROCESS_CMDLINE_QUOTE_POSIX = 1 << 3,
} ProcessCmdlineFlags;
int get_process_comm(pid_t pid, char **ret);
int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret);
int get_process_exe(pid_t pid, char **ret);
int get_process_uid(pid_t pid, uid_t *ret);
int get_process_gid(pid_t pid, gid_t *ret);
int get_process_capeff(pid_t pid, char **ret);
int get_process_cwd(pid_t pid, char **ret);
int get_process_root(pid_t pid, char **ret);
int get_process_environ(pid_t pid, char **ret);
int get_process_ppid(pid_t pid, pid_t *ret);
int get_process_umask(pid_t pid, mode_t *ret);
int get_process_comm(pid_t pid, char **name);
int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **line);
int get_process_exe(pid_t pid, char **name);
int get_process_uid(pid_t pid, uid_t *uid);
int get_process_gid(pid_t pid, gid_t *gid);
int get_process_capeff(pid_t pid, char **capeff);
int get_process_cwd(pid_t pid, char **cwd);
int get_process_root(pid_t pid, char **root);
int get_process_environ(pid_t pid, char **environ);
int get_process_ppid(pid_t pid, pid_t *ppid);
int get_process_umask(pid_t pid, mode_t *umask);
int wait_for_terminate(pid_t pid, siginfo_t *status);

View File

@ -148,7 +148,6 @@ static int target_serialize(Unit *u, FILE *f, FDSet *fds) {
static int target_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
Target *s = TARGET(u);
assert(s);
assert(u);
assert(key);
assert(value);

View File

@ -2304,8 +2304,8 @@ static int unit_log_resources(Unit *u) {
message_parts[n_message_parts++] = t;
log_level = raise_level(log_level,
nsec > MENTIONWORTHY_CPU_NSEC,
nsec > NOTICEWORTHY_CPU_NSEC);
nsec > NOTICEWORTHY_CPU_NSEC,
nsec > MENTIONWORTHY_CPU_NSEC);
}
for (CGroupIOAccountingMetric k = 0; k < _CGROUP_IO_ACCOUNTING_METRIC_MAX; k++) {

View File

@ -91,144 +91,6 @@
# pragma GCC diagnostic ignored "-Waddress-of-packed-member"
#endif
static int journal_file_tail_end(JournalFile *f, uint64_t *ret_offset) {
Object tail;
uint64_t p;
int r;
assert(f);
assert(f->header);
assert(ret_offset);
p = le64toh(f->header->tail_object_offset);
if (p == 0)
p = le64toh(f->header->header_size);
else {
uint64_t sz;
r = journal_file_read_object(f, OBJECT_UNUSED, p, &tail);
if (r < 0)
return r;
sz = le64toh(tail.object.size);
if (sz > UINT64_MAX - sizeof(uint64_t) + 1)
return -EBADMSG;
sz = ALIGN64(sz);
if (p > UINT64_MAX - sz)
return -EBADMSG;
p += sz;
}
*ret_offset = p;
return 0;
}
static int journal_file_truncate(JournalFile *f) {
uint64_t p;
int r;
/* truncate excess from the end of archives */
r = journal_file_tail_end(f, &p);
if (r < 0)
return log_debug_errno(r, "Failed to determine end of tail object: %m");
/* arena_size can't exceed the file size, ensure it's updated before truncating */
f->header->arena_size = htole64(p - le64toh(f->header->header_size));
if (ftruncate(f->fd, p) < 0)
log_debug_errno(errno, "Failed to truncate %s: %m", f->path);
return 0;
}
static int journal_file_entry_array_punch_hole(JournalFile *f, uint64_t p, uint64_t n_entries) {
Object o;
uint64_t offset, sz, n_items = 0, n_unused;
int r;
if (n_entries == 0)
return 0;
for (uint64_t q = p; q != 0; q = le64toh(o.entry_array.next_entry_array_offset)) {
r = journal_file_read_object(f, OBJECT_ENTRY_ARRAY, q, &o);
if (r < 0)
return r;
n_items += journal_file_entry_array_n_items(&o);
p = q;
}
if (p == 0)
return 0;
if (n_entries > n_items)
return -EBADMSG;
/* Amount of unused items in the final entry array. */
n_unused = n_items - n_entries;
if (n_unused == 0)
return 0;
offset = p + offsetof(Object, entry_array.items) +
(journal_file_entry_array_n_items(&o) - n_unused) * sizeof(le64_t);
sz = p + le64toh(o.object.size) - offset;
if (fallocate(f->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, offset, sz) < 0)
return log_debug_errno(errno, "Failed to punch hole in entry array of %s: %m", f->path);
return 0;
}
static int journal_file_punch_holes(JournalFile *f) {
HashItem items[4096 / sizeof(HashItem)];
uint64_t p, sz;
size_t to_read;
int r;
r = journal_file_entry_array_punch_hole(
f, le64toh(f->header->entry_array_offset), le64toh(f->header->n_entries));
if (r < 0)
return r;
p = le64toh(f->header->data_hash_table_offset);
sz = le64toh(f->header->data_hash_table_size);
to_read = MIN((size_t) f->last_stat.st_blksize, sizeof(items));
for (uint64_t i = p; i < p + sz; i += sizeof(items)) {
ssize_t n_read;
n_read = pread(f->fd, items, MIN(to_read, p + sz - i), i);
if (n_read < 0)
return n_read;
for (size_t j = 0; j < (size_t) n_read / sizeof(HashItem); j++) {
Object o;
for (uint64_t q = le64toh(items[j].head_hash_offset); q != 0;
q = le64toh(o.data.next_hash_offset)) {
r = journal_file_read_object(f, OBJECT_DATA, q, &o);
if (r < 0) {
log_debug_errno(r, "Invalid data object: %m, ignoring");
break;
}
if (le64toh(o.data.n_entries) == 0)
continue;
(void) journal_file_entry_array_punch_hole(
f, le64toh(o.data.entry_array_offset), le64toh(o.data.n_entries) - 1);
}
}
}
return 0;
}
/* This may be called from a separate thread to prevent blocking the caller for the duration of fsync().
* As a result we use atomic operations on f->offline_state for inter-thread communications with
* journal_file_set_offline() and journal_file_set_online(). */
@ -255,11 +117,6 @@ static void journal_file_set_offline_internal(JournalFile *f) {
break;
case OFFLINE_SYNCING:
if (f->archive) {
(void) journal_file_truncate(f);
(void) journal_file_punch_holes(f);
}
(void) fsync(f->fd);
if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_SYNCING, OFFLINE_OFFLINING))
@ -1133,65 +990,6 @@ int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset
return 0;
}
int journal_file_read_object(JournalFile *f, ObjectType type, uint64_t offset, Object *ret) {
int r;
Object o;
uint64_t s;
assert(f);
assert(ret);
/* Objects may only be located at multiple of 64 bit */
if (!VALID64(offset))
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
"Attempt to read object at non-64bit boundary: %" PRIu64,
offset);
/* Object may not be located in the file header */
if (offset < le64toh(f->header->header_size))
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
"Attempt to read object located in file header: %" PRIu64,
offset);
/* This will likely read too much data but it avoids having to call pread() twice. */
r = pread(f->fd, &o, sizeof(Object), offset);
if (r < 0)
return r;
s = le64toh(o.object.size);
if (s == 0)
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
"Attempt to read uninitialized object: %" PRIu64,
offset);
if (s < sizeof(ObjectHeader))
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
"Attempt to read overly short object: %" PRIu64,
offset);
if (o.object.type <= OBJECT_UNUSED)
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
"Attempt to read object with invalid type: %" PRIu64,
offset);
if (s < minimum_header_size(&o))
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
"Attempt to read truncated object: %" PRIu64,
offset);
if (type > OBJECT_UNUSED && o.object.type != type)
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
"Attempt to read object of unexpected type: %" PRIu64,
offset);
r = journal_file_check_object(f, offset, &o);
if (r < 0)
return r;
*ret = o;
return 0;
}
static uint64_t journal_file_entry_seqnum(
JournalFile *f,
uint64_t *seqnum) {
@ -1232,7 +1030,7 @@ int journal_file_append_object(
int r;
uint64_t p;
Object *o;
Object *tail, *o;
void *t;
assert(f);
@ -1244,9 +1042,26 @@ int journal_file_append_object(
if (r < 0)
return r;
r = journal_file_tail_end(f, &p);
if (r < 0)
return r;
p = le64toh(f->header->tail_object_offset);
if (p == 0)
p = le64toh(f->header->header_size);
else {
uint64_t sz;
r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &tail);
if (r < 0)
return r;
sz = le64toh(READ_NOW(tail->object.size));
if (sz > UINT64_MAX - sizeof(uint64_t) + 1)
return -EBADMSG;
sz = ALIGN64(sz);
if (p > UINT64_MAX - sz)
return -EBADMSG;
p += sz;
}
r = journal_file_allocate(f, p, size);
if (r < 0)

View File

@ -202,7 +202,6 @@ static inline bool VALID_EPOCH(uint64_t u) {
FLAGS_SET(le32toh((h)->incompatible_flags), HEADER_INCOMPATIBLE_KEYED_HASH)
int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset, Object **ret);
int journal_file_read_object(JournalFile *f, ObjectType type, uint64_t offset, Object *ret);
uint64_t journal_file_entry_n_items(Object *o) _pure_;
uint64_t journal_file_entry_array_n_items(Object *o) _pure_;

View File

@ -570,6 +570,47 @@ static int dhcp6_pd_assign_prefix(
return 1;
}
static int dhcp6_pd_distribute_prefix(
Link *dhcp6_link,
const struct in6_addr *pd_prefix,
uint8_t pd_prefix_len,
usec_t lifetime_preferred_usec,
usec_t lifetime_valid_usec) {
Link *link;
int r;
assert(dhcp6_link);
assert(dhcp6_link->manager);
assert(pd_prefix);
assert(pd_prefix_len <= 64);
HASHMAP_FOREACH(link, dhcp6_link->manager->links_by_index) {
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
continue;
if (!dhcp6_pd_is_uplink(link, dhcp6_link, /* accept_auto = */ true))
continue;
if (link->network->dhcp6_pd_announce && !link->radv)
continue;
if (link == dhcp6_link && !link->network->dhcp6_pd_assign)
continue;
r = dhcp6_pd_assign_prefix(link, pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec);
if (r < 0) {
if (link == dhcp6_link)
return r;
link_enter_failed(link);
continue;
}
}
return 0;
}
static int dhcp6_pd_prepare(Link *link) {
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
return 0;
@ -583,7 +624,7 @@ static int dhcp6_pd_prepare(Link *link) {
link_mark_addresses(link, NETWORK_CONFIG_SOURCE_DHCP6PD, NULL);
link_mark_routes(link, NETWORK_CONFIG_SOURCE_DHCP6PD, NULL);
return 1;
return 0;
}
static int dhcp6_pd_finalize(Link *link) {
@ -592,6 +633,12 @@ static int dhcp6_pd_finalize(Link *link) {
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
return 0;
if (!link_dhcp6_pd_is_enabled(link))
return 0;
if (link->network->dhcp6_pd_announce && !link->radv)
return 0;
if (link->dhcp6_pd_messages == 0) {
link->dhcp6_pd_configured = false;
@ -746,6 +793,103 @@ static int dhcp6_pd_prefix_add(Link *link, const struct in6_addr *prefix, uint8_
return prefixlen <= 64;
}
int dhcp6_pd_prefix_acquired(Link *dhcp6_link) {
usec_t timestamp_usec;
Link *link;
int r;
assert(dhcp6_link);
assert(dhcp6_link->dhcp6_lease);
r = sd_dhcp6_lease_get_timestamp(dhcp6_link->dhcp6_lease, clock_boottime_or_monotonic(), &timestamp_usec);
if (r < 0)
return log_link_warning_errno(dhcp6_link, r, "Failed to get timestamp of DHCPv6 lease: %m");
HASHMAP_FOREACH(link, dhcp6_link->manager->links_by_index) {
r = dhcp6_pd_prepare(link);
if (r < 0) {
/* When failed on the upstream interface (i.e., the case link == dhcp6_link),
* immediately abort the assignment of the prefixes. As, the all assigned
* prefixes will be dropped soon in link_enter_failed(), and it is meaningless
* to continue the assignment. */
if (link == dhcp6_link)
return r;
link_enter_failed(link);
}
}
for (sd_dhcp6_lease_reset_pd_prefix_iter(dhcp6_link->dhcp6_lease);;) {
uint32_t lifetime_preferred_sec, lifetime_valid_sec;
usec_t lifetime_preferred_usec, lifetime_valid_usec;
struct in6_addr pd_prefix;
uint8_t pd_prefix_len;
r = sd_dhcp6_lease_get_pd(dhcp6_link->dhcp6_lease, &pd_prefix, &pd_prefix_len,
&lifetime_preferred_sec, &lifetime_valid_sec);
if (r < 0)
break;
lifetime_preferred_usec = usec_add(lifetime_preferred_sec * USEC_PER_SEC, timestamp_usec);
lifetime_valid_usec = usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec);
r = dhcp6_pd_prefix_add(dhcp6_link, &pd_prefix, pd_prefix_len);
if (r < 0)
return r;
if (r == 0)
continue;
r = dhcp6_request_unreachable_route(dhcp6_link, &pd_prefix, pd_prefix_len, lifetime_valid_usec);
if (r < 0)
return r;
/* We are doing prefix allocation in two steps:
* 1. all those links that have a preferred subnet id will be assigned their subnet
* 2. all those links that remain will receive prefixes in sequential order. Prefixes
* that were previously already allocated to another link will be skipped.
* The assignment has to be split in two phases since subnet id
* preferences should be honored. Meaning that any subnet id should be
* handed out to the requesting link and not to some link that didn't
* specify any preference. */
assert(pd_prefix_len <= 64);
/* Mask prefix for safety. */
r = in6_addr_mask(&pd_prefix, pd_prefix_len);
if (r < 0)
return log_link_error_errno(dhcp6_link, r, "Failed to mask DHCPv6 PD prefix: %m");
if (DEBUG_LOGGING) {
uint64_t n_prefixes = UINT64_C(1) << (64 - pd_prefix_len);
_cleanup_free_ char *buf = NULL;
(void) in6_addr_prefix_to_string(&pd_prefix, pd_prefix_len, &buf);
log_link_debug(dhcp6_link, "Assigning up to %" PRIu64 " prefixes from %s",
n_prefixes, strna(buf));
}
r = dhcp6_pd_distribute_prefix(dhcp6_link,
&pd_prefix,
pd_prefix_len,
lifetime_preferred_usec,
lifetime_valid_usec);
if (r < 0)
return r;
}
HASHMAP_FOREACH(link, dhcp6_link->manager->links_by_index) {
r = dhcp6_pd_finalize(link);
if (r < 0) {
if (link == dhcp6_link)
return r;
link_enter_failed(link);
}
}
return 0;
}
static int dhcp6_pd_assign_prefixes(Link *link, Link *uplink) {
usec_t timestamp_usec;
int r;
@ -754,14 +898,17 @@ static int dhcp6_pd_assign_prefixes(Link *link, Link *uplink) {
assert(uplink);
assert(uplink->dhcp6_lease);
r = dhcp6_pd_prepare(link);
if (r <= 0)
return r;
/* This is similar to dhcp6_pd_prefix_acquired(), but called when a downstream interface
* appears later or reconfiguring the interface. */
r = sd_dhcp6_lease_get_timestamp(uplink->dhcp6_lease, clock_boottime_or_monotonic(), &timestamp_usec);
if (r < 0)
return r;
r = dhcp6_pd_prepare(link);
if (r < 0)
return r;
for (sd_dhcp6_lease_reset_pd_prefix_iter(uplink->dhcp6_lease);;) {
uint32_t lifetime_preferred_sec, lifetime_valid_sec;
usec_t lifetime_preferred_usec, lifetime_valid_usec;
@ -773,6 +920,9 @@ static int dhcp6_pd_assign_prefixes(Link *link, Link *uplink) {
if (r < 0)
break;
lifetime_preferred_usec = usec_add(lifetime_preferred_sec * USEC_PER_SEC, timestamp_usec);
lifetime_valid_usec = usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec);
if (pd_prefix_len > 64)
continue;
@ -781,76 +931,14 @@ static int dhcp6_pd_assign_prefixes(Link *link, Link *uplink) {
if (r < 0)
return r;
lifetime_preferred_usec = usec_add(lifetime_preferred_sec * USEC_PER_SEC, timestamp_usec);
lifetime_valid_usec = usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec);
r = dhcp6_pd_assign_prefix(link, &pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec);
if (r < 0)
return r;
}
return dhcp6_pd_finalize(link);
}
int dhcp6_pd_prefix_acquired(Link *dhcp6_link) {
usec_t timestamp_usec;
Link *link;
int r;
assert(dhcp6_link);
assert(dhcp6_link->dhcp6_lease);
r = sd_dhcp6_lease_get_timestamp(dhcp6_link->dhcp6_lease, clock_boottime_or_monotonic(), &timestamp_usec);
r = dhcp6_pd_finalize(link);
if (r < 0)
return log_link_warning_errno(dhcp6_link, r, "Failed to get timestamp of DHCPv6 lease: %m");
/* First, logs acquired prefixes and request unreachable routes. */
for (sd_dhcp6_lease_reset_pd_prefix_iter(dhcp6_link->dhcp6_lease);;) {
uint32_t lifetime_preferred_sec, lifetime_valid_sec;
usec_t lifetime_valid_usec;
struct in6_addr pd_prefix;
uint8_t pd_prefix_len;
r = sd_dhcp6_lease_get_pd(dhcp6_link->dhcp6_lease, &pd_prefix, &pd_prefix_len,
&lifetime_preferred_sec, &lifetime_valid_sec);
if (r < 0)
break;
/* Mask prefix for safety. */
r = in6_addr_mask(&pd_prefix, pd_prefix_len);
if (r < 0)
return log_link_error_errno(dhcp6_link, r, "Failed to mask DHCPv6 PD prefix: %m");
lifetime_valid_usec = usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec);
r = dhcp6_pd_prefix_add(dhcp6_link, &pd_prefix, pd_prefix_len);
if (r < 0)
return r;
if (r == 0)
continue;
r = dhcp6_request_unreachable_route(dhcp6_link, &pd_prefix, pd_prefix_len, lifetime_valid_usec);
if (r < 0)
return r;
}
/* Then, assign subnet prefixes. */
HASHMAP_FOREACH(link, dhcp6_link->manager->links_by_index) {
if (!dhcp6_pd_is_uplink(link, dhcp6_link, /* accept_auto = */ true))
continue;
r = dhcp6_pd_assign_prefixes(link, dhcp6_link);
if (r < 0) {
/* When failed on the upstream interface (i.e., the case link == dhcp6_link),
* immediately abort the assignment of the prefixes. As, the all assigned
* prefixes will be dropped soon in link_enter_failed(), and it is meaningless
* to continue the assignment. */
if (link == dhcp6_link)
return r;
link_enter_failed(link);
}
}
return r;
return 0;
}

View File

@ -350,11 +350,6 @@ static void print_link_hashmap(FILE *f, const char *prefix, Hashmap* h) {
}
static void link_save_dns(Link *link, FILE *f, struct in_addr_full **dns, unsigned n_dns, bool *space) {
bool _space = false;
if (!space)
space = &_space;
for (unsigned j = 0; j < n_dns; j++) {
const char *str;
@ -423,45 +418,6 @@ static void serialize_addresses(
fputc('\n', f);
}
static void link_save_domains(Link *link, FILE *f, OrderedSet *static_domains, DHCPUseDomains use_domains) {
bool space = false;
const char *p;
assert(link);
assert(link->network);
assert(f);
ORDERED_SET_FOREACH(p, static_domains)
fputs_with_space(f, p, NULL, &space);
if (use_domains == DHCP_USE_DOMAINS_NO)
return;
if (link->dhcp_lease && link->network->dhcp_use_domains == use_domains) {
const char *domainname;
char **domains;
if (sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname) >= 0)
fputs_with_space(f, domainname, NULL, &space);
if (sd_dhcp_lease_get_search_domains(link->dhcp_lease, &domains) >= 0)
fputstrv(f, domains, NULL, &space);
}
if (link->dhcp6_lease && link->network->dhcp6_use_domains == use_domains) {
char **domains;
if (sd_dhcp6_lease_get_domains(link->dhcp6_lease, &domains) >= 0)
fputstrv(f, domains, NULL, &space);
}
if (link->network->ipv6_accept_ra_use_domains == use_domains) {
NDiscDNSSL *dd;
SET_FOREACH(dd, link->ndisc_dnssl)
fputs_with_space(f, NDISC_DNSSL_DOMAIN(dd), NULL, &space);
}
}
int link_save(Link *link) {
const char *admin_state, *oper_state, *carrier_state, *address_state, *ipv4_address_state, *ipv6_address_state;
_cleanup_(unlink_and_freep) char *temp_path = NULL;
@ -514,7 +470,8 @@ int link_save(Link *link) {
admin_state, oper_state, carrier_state, address_state, ipv4_address_state, ipv6_address_state);
if (link->network) {
const char *online_state;
char **dhcp6_domains = NULL, **dhcp_domains = NULL;
const char *dhcp_domainname = NULL, *online_state, *p;
bool space;
online_state = link_online_state_to_string(link->online_state);
@ -540,52 +497,46 @@ int link_save(Link *link) {
/************************************************************/
fputs("DNS=", f);
space = false;
if (link->n_dns != UINT_MAX)
link_save_dns(link, f, link->dns, link->n_dns, &space);
else
link_save_dns(link, f, link->network->dns, link->network->n_dns, &space);
serialize_addresses(f, NULL, &space,
NULL,
link->dhcp_lease,
link->network->dhcp_use_dns,
SD_DHCP_LEASE_DNS,
link->dhcp6_lease,
link->network->dhcp6_use_dns,
sd_dhcp6_lease_get_dns,
NULL);
/* Make sure to flush out old entries before we use the NDisc data */
ndisc_vacuum(link);
fputs("DNS=", f);
if (link->n_dns != UINT_MAX)
link_save_dns(link, f, link->dns, link->n_dns, NULL);
else {
space = false;
link_save_dns(link, f, link->network->dns, link->network->n_dns, &space);
if (link->network->ipv6_accept_ra_use_dns && link->ndisc_rdnss) {
NDiscRDNSS *dd;
serialize_addresses(f, NULL, &space,
NULL,
link->dhcp_lease,
link->network->dhcp_use_dns,
SD_DHCP_LEASE_DNS,
link->dhcp6_lease,
link->network->dhcp6_use_dns,
sd_dhcp6_lease_get_dns,
NULL);
if (link->network->ipv6_accept_ra_use_dns) {
NDiscRDNSS *dd;
SET_FOREACH(dd, link->ndisc_rdnss)
serialize_in6_addrs(f, &dd->address, 1, &space);
}
SET_FOREACH(dd, link->ndisc_rdnss)
serialize_in6_addrs(f, &dd->address, 1, &space);
}
fputc('\n', f);
/************************************************************/
if (link->ntp) {
fputs("NTP=", f);
fputstrv(f, link->ntp, NULL, NULL);
fputc('\n', f);
} else
serialize_addresses(f, "NTP", NULL,
link->network->ntp,
link->dhcp_lease,
link->network->dhcp_use_ntp,
SD_DHCP_LEASE_NTP,
link->dhcp6_lease,
link->network->dhcp6_use_ntp,
sd_dhcp6_lease_get_ntp_addrs,
sd_dhcp6_lease_get_ntp_fqdn);
serialize_addresses(f, "NTP", NULL,
link->ntp ?: link->network->ntp,
link->dhcp_lease,
link->network->dhcp_use_ntp,
SD_DHCP_LEASE_NTP,
link->dhcp6_lease,
link->network->dhcp6_use_ntp,
sd_dhcp6_lease_get_ntp_addrs,
sd_dhcp6_lease_get_ntp_fqdn);
serialize_addresses(f, "SIP", NULL,
NULL,
@ -596,20 +547,59 @@ int link_save(Link *link) {
/************************************************************/
if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO && link->dhcp_lease) {
(void) sd_dhcp_lease_get_domainname(link->dhcp_lease, &dhcp_domainname);
(void) sd_dhcp_lease_get_search_domains(link->dhcp_lease, &dhcp_domains);
}
if (link->network->dhcp6_use_domains != DHCP_USE_DOMAINS_NO && link->dhcp6_lease)
(void) sd_dhcp6_lease_get_domains(link->dhcp6_lease, &dhcp6_domains);
fputs("DOMAINS=", f);
if (link->search_domains)
link_save_domains(link, f, link->search_domains, DHCP_USE_DOMAINS_NO);
else
link_save_domains(link, f, link->network->search_domains, DHCP_USE_DOMAINS_YES);
space = false;
ORDERED_SET_FOREACH(p, link->search_domains ?: link->network->search_domains)
fputs_with_space(f, p, NULL, &space);
if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES) {
if (dhcp_domainname)
fputs_with_space(f, dhcp_domainname, NULL, &space);
if (dhcp_domains)
fputstrv(f, dhcp_domains, NULL, &space);
if (dhcp6_domains)
fputstrv(f, dhcp6_domains, NULL, &space);
}
if (link->network->ipv6_accept_ra_use_domains == DHCP_USE_DOMAINS_YES) {
NDiscDNSSL *dd;
SET_FOREACH(dd, link->ndisc_dnssl)
fputs_with_space(f, NDISC_DNSSL_DOMAIN(dd), NULL, &space);
}
fputc('\n', f);
/************************************************************/
fputs("ROUTE_DOMAINS=", f);
if (link->route_domains)
link_save_domains(link, f, link->route_domains, DHCP_USE_DOMAINS_NO);
else
link_save_domains(link, f, link->network->route_domains, DHCP_USE_DOMAINS_ROUTE);
space = false;
ORDERED_SET_FOREACH(p, link->route_domains ?: link->network->route_domains)
fputs_with_space(f, p, NULL, &space);
if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE) {
if (dhcp_domainname)
fputs_with_space(f, dhcp_domainname, NULL, &space);
if (dhcp_domains)
fputstrv(f, dhcp_domains, NULL, &space);
if (dhcp6_domains)
fputstrv(f, dhcp6_domains, NULL, &space);
}
if (link->network->ipv6_accept_ra_use_domains == DHCP_USE_DOMAINS_ROUTE) {
NDiscDNSSL *dd;
SET_FOREACH(dd, link->ndisc_dnssl)
fputs_with_space(f, NDISC_DNSSL_DOMAIN(dd), NULL, &space);
}
fputc('\n', f);
/************************************************************/

View File

@ -170,7 +170,7 @@ int dns_answer_add(
/* Entry already exists, keep the entry with the higher TTL. */
if (rr->ttl > exist->rr->ttl) {
dns_resource_record_unref(exist->rr);
exist->rr = dns_resource_record_ref(rr); /* lgtm [cpp/inconsistent-null-check] */
exist->rr = dns_resource_record_ref(rr);
/* Update RRSIG and RR at the same time */
if (rrsig) {

View File

@ -484,8 +484,8 @@ TEST(get_process_cmdline_harder) {
/* Test with multiple arguments that do require quoting */
#define CMDLINE1 "foo\0'bar'\0\"bar$\"\0x y z\0!``\0"
#define EXPECT1 "foo \"'bar'\" \"\\\"bar\\$\\\"\" \"x y z\" \"!\\`\\`\""
#define EXPECT1p "foo $'\\'bar\\'' $'\"bar$\"' $'x y z' $'!``'"
#define EXPECT1 "foo \"'bar'\" \"\\\"bar\\$\\\"\" \"x y z\" \"!\\`\\`\" \"\""
#define EXPECT1p "foo $'\\'bar\\'' $'\"bar$\"' $'x y z' $'!``' \"\""
assert_se(lseek(fd, SEEK_SET, 0) == 0);
assert_se(write(fd, CMDLINE1, sizeof CMDLINE1) == sizeof CMDLINE1);
assert_se(ftruncate(fd, sizeof CMDLINE1) == 0);
@ -503,8 +503,8 @@ TEST(get_process_cmdline_harder) {
line = mfree(line);
#define CMDLINE2 "foo\0\1\2\3\0\0"
#define EXPECT2 "foo \"\\001\\002\\003\""
#define EXPECT2p "foo $'\\001\\002\\003'"
#define EXPECT2 "foo \"\\001\\002\\003\" \"\" \"\""
#define EXPECT2p "foo $'\\001\\002\\003' \"\" \"\""
assert_se(lseek(fd, SEEK_SET, 0) == 0);
assert_se(write(fd, CMDLINE2, sizeof CMDLINE2) == sizeof CMDLINE2);
assert_se(ftruncate(fd, sizeof CMDLINE2) == 0);

View File

@ -175,6 +175,7 @@ BASICTOOLS=(
sfdisk
sh
sleep
socat
stat
su
sulogin

View File

@ -7,7 +7,8 @@ ExecStartPre=rm -f /failed /testok
Type=oneshot
ExecStart=rm -f /tmp/nonexistent
ExecStart=systemctl start test10.socket
ExecStart=-nc -w20 -U /run/test.ctl
ExecStart=sh -x -c 'printf x >test.file'
ExecStart=-socat -T20 OPEN:test.file UNIX-CONNECT:/run/test.ctl
# TriggerLimitIntervalSec= by default is set to 2s. A "sleep 10" should give
# systemd enough time even on slower machines, to reach the trigger limit.
ExecStart=sleep 10