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.
f836390fa7
...
de1253e4c6
6
.github/workflows/codeql-analysis.yml
vendored
6
.github/workflows/codeql-analysis.yml
vendored
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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++) {
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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_;
|
||||
|
||||
@ -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(), ×tamp_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(), ×tamp_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(), ×tamp_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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
/************************************************************/
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -175,6 +175,7 @@ BASICTOOLS=(
|
||||
sfdisk
|
||||
sh
|
||||
sleep
|
||||
socat
|
||||
stat
|
||||
su
|
||||
sulogin
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user