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
|
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@546b30f35ae5a3db0e0be1843008c2224f71c3b0
|
uses: github/codeql-action/init@e095058bfa09de8070f94e98f5dc059531bc6235
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
|
|
||||||
- run: sudo -E .github/workflows/unit_tests.sh SETUP
|
- run: sudo -E .github/workflows/unit_tests.sh SETUP
|
||||||
|
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@546b30f35ae5a3db0e0be1843008c2224f71c3b0
|
uses: github/codeql-action/autobuild@e095058bfa09de8070f94e98f5dc059531bc6235
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- 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;
|
return r;
|
||||||
|
|
||||||
STRV_FOREACH(c, deps) {
|
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)
|
if (times_in_range(times, boot) && times->activated >= service_longest)
|
||||||
service_longest = times->activated;
|
service_longest = times->activated;
|
||||||
}
|
}
|
||||||
@ -991,7 +991,7 @@ static int list_dependencies_one(sd_bus *bus, const char *name, unsigned level,
|
|||||||
return r;
|
return r;
|
||||||
|
|
||||||
STRV_FOREACH(c, deps) {
|
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)
|
if (times_in_range(times, boot) && service_longest - times->activated <= arg_fuzz)
|
||||||
to_print++;
|
to_print++;
|
||||||
}
|
}
|
||||||
@ -1000,7 +1000,7 @@ static int list_dependencies_one(sd_bus *bus, const char *name, unsigned level,
|
|||||||
return r;
|
return r;
|
||||||
|
|
||||||
STRV_FOREACH(c, deps) {
|
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)
|
if (!times_in_range(times, boot) || service_longest - times->activated > arg_fuzz)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@ -181,13 +181,13 @@ static int get_process_cmdline_nulstr(
|
|||||||
return r;
|
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;
|
_cleanup_free_ char *t = NULL;
|
||||||
size_t k;
|
size_t k;
|
||||||
char *ans;
|
char *ans;
|
||||||
|
|
||||||
|
assert(line);
|
||||||
assert(pid >= 0);
|
assert(pid >= 0);
|
||||||
assert(ret);
|
|
||||||
|
|
||||||
/* Retrieve and format a commandline. See above for discussion of retrieval options.
|
/* 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));
|
assert(!(flags & PROCESS_CMDLINE_USE_LOCALE));
|
||||||
|
|
||||||
_cleanup_strv_free_ char **args = NULL;
|
_cleanup_strv_free_ char **args = NULL;
|
||||||
char **p;
|
|
||||||
|
|
||||||
args = strv_parse_nulstr(t, k);
|
args = strv_parse_nulstr(t, k);
|
||||||
if (!args)
|
if (!args)
|
||||||
return -ENOMEM;
|
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);
|
ans = quote_command_line(args, shflags);
|
||||||
if (!ans)
|
if (!ans)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -246,7 +240,7 @@ int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags
|
|||||||
ans = str_realloc(ans);
|
ans = str_realloc(ans);
|
||||||
}
|
}
|
||||||
|
|
||||||
*ret = ans;
|
*line = ans;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -453,29 +447,29 @@ int is_kernel_thread(pid_t pid) {
|
|||||||
return !!(flags & PF_KTHREAD);
|
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;
|
const char *p;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
assert(capeff);
|
||||||
assert(pid >= 0);
|
assert(pid >= 0);
|
||||||
assert(ret);
|
|
||||||
|
|
||||||
p = procfs_file_alloca(pid, "status");
|
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)
|
if (r == -ENOENT)
|
||||||
return -ESRCH;
|
return -ESRCH;
|
||||||
|
|
||||||
return r;
|
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;
|
int r;
|
||||||
|
|
||||||
assert(proc_file);
|
assert(proc_file);
|
||||||
assert(ret);
|
assert(name);
|
||||||
|
|
||||||
r = readlink_malloc(proc_file, ret);
|
r = readlink_malloc(proc_file, name);
|
||||||
if (r == -ENOENT)
|
if (r == -ENOENT)
|
||||||
return -ESRCH;
|
return -ESRCH;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -484,33 +478,32 @@ static int get_process_link_contents(const char *proc_file, char **ret) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_process_exe(pid_t pid, char **ret) {
|
int get_process_exe(pid_t pid, char **name) {
|
||||||
const char *p;
|
const char *p;
|
||||||
char *d;
|
char *d;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(pid >= 0);
|
assert(pid >= 0);
|
||||||
assert(ret);
|
|
||||||
|
|
||||||
p = procfs_file_alloca(pid, "exe");
|
p = procfs_file_alloca(pid, "exe");
|
||||||
r = get_process_link_contents(p, ret);
|
r = get_process_link_contents(p, name);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
d = endswith(*ret, " (deleted)");
|
d = endswith(*name, " (deleted)");
|
||||||
if (d)
|
if (d)
|
||||||
*d = '\0';
|
*d = '\0';
|
||||||
|
|
||||||
return 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;
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
const char *p;
|
const char *p;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(field);
|
assert(field);
|
||||||
assert(ret);
|
assert(uid);
|
||||||
|
|
||||||
if (pid < 0)
|
if (pid < 0)
|
||||||
return -EINVAL;
|
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;
|
l[strcspn(l, WHITESPACE)] = 0;
|
||||||
|
|
||||||
return parse_uid(l, ret);
|
return parse_uid(l, uid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -EIO;
|
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()) {
|
if (pid == 0 || pid == getpid_cached()) {
|
||||||
*ret = getuid();
|
*uid = getuid();
|
||||||
return 0;
|
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()) {
|
if (pid == 0 || pid == getpid_cached()) {
|
||||||
*ret = getgid();
|
*gid = getgid();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_cc(sizeof(uid_t) == sizeof(gid_t));
|
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;
|
const char *p;
|
||||||
|
|
||||||
assert(pid >= 0);
|
assert(pid >= 0);
|
||||||
assert(ret);
|
|
||||||
|
|
||||||
if (pid == 0 || pid == getpid_cached())
|
if (pid == 0 || pid == getpid_cached())
|
||||||
return safe_getcwd(ret);
|
return safe_getcwd(cwd);
|
||||||
|
|
||||||
p = procfs_file_alloca(pid, "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;
|
const char *p;
|
||||||
|
|
||||||
assert(pid >= 0);
|
assert(pid >= 0);
|
||||||
assert(ret);
|
|
||||||
|
|
||||||
p = procfs_file_alloca(pid, "root");
|
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)
|
#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_fclose_ FILE *f = NULL;
|
||||||
_cleanup_free_ char *outcome = NULL;
|
_cleanup_free_ char *outcome = NULL;
|
||||||
size_t sz = 0;
|
size_t sz = 0;
|
||||||
@ -603,7 +594,7 @@ int get_process_environ(pid_t pid, char **ret) {
|
|||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(pid >= 0);
|
assert(pid >= 0);
|
||||||
assert(ret);
|
assert(env);
|
||||||
|
|
||||||
p = procfs_file_alloca(pid, "environ");
|
p = procfs_file_alloca(pid, "environ");
|
||||||
|
|
||||||
@ -635,7 +626,7 @@ int get_process_environ(pid_t pid, char **ret) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
outcome[sz] = '\0';
|
outcome[sz] = '\0';
|
||||||
*ret = TAKE_PTR(outcome);
|
*env = TAKE_PTR(outcome);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -694,13 +685,13 @@ int get_process_ppid(pid_t pid, pid_t *ret) {
|
|||||||
return 0;
|
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;
|
_cleanup_free_ char *m = NULL;
|
||||||
const char *p;
|
const char *p;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
assert(umask);
|
||||||
assert(pid >= 0);
|
assert(pid >= 0);
|
||||||
assert(ret);
|
|
||||||
|
|
||||||
p = procfs_file_alloca(pid, "status");
|
p = procfs_file_alloca(pid, "status");
|
||||||
|
|
||||||
@ -708,7 +699,7 @@ int get_process_umask(pid_t pid, mode_t *ret) {
|
|||||||
if (r == -ENOENT)
|
if (r == -ENOENT)
|
||||||
return -ESRCH;
|
return -ESRCH;
|
||||||
|
|
||||||
return parse_mode(m, ret);
|
return parse_mode(m, umask);
|
||||||
}
|
}
|
||||||
|
|
||||||
int wait_for_terminate(pid_t pid, siginfo_t *status) {
|
int wait_for_terminate(pid_t pid, siginfo_t *status) {
|
||||||
|
|||||||
@ -38,17 +38,17 @@ typedef enum ProcessCmdlineFlags {
|
|||||||
PROCESS_CMDLINE_QUOTE_POSIX = 1 << 3,
|
PROCESS_CMDLINE_QUOTE_POSIX = 1 << 3,
|
||||||
} ProcessCmdlineFlags;
|
} ProcessCmdlineFlags;
|
||||||
|
|
||||||
int get_process_comm(pid_t pid, char **ret);
|
int get_process_comm(pid_t pid, char **name);
|
||||||
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);
|
||||||
int get_process_exe(pid_t pid, char **ret);
|
int get_process_exe(pid_t pid, char **name);
|
||||||
int get_process_uid(pid_t pid, uid_t *ret);
|
int get_process_uid(pid_t pid, uid_t *uid);
|
||||||
int get_process_gid(pid_t pid, gid_t *ret);
|
int get_process_gid(pid_t pid, gid_t *gid);
|
||||||
int get_process_capeff(pid_t pid, char **ret);
|
int get_process_capeff(pid_t pid, char **capeff);
|
||||||
int get_process_cwd(pid_t pid, char **ret);
|
int get_process_cwd(pid_t pid, char **cwd);
|
||||||
int get_process_root(pid_t pid, char **ret);
|
int get_process_root(pid_t pid, char **root);
|
||||||
int get_process_environ(pid_t pid, char **ret);
|
int get_process_environ(pid_t pid, char **environ);
|
||||||
int get_process_ppid(pid_t pid, pid_t *ret);
|
int get_process_ppid(pid_t pid, pid_t *ppid);
|
||||||
int get_process_umask(pid_t pid, mode_t *ret);
|
int get_process_umask(pid_t pid, mode_t *umask);
|
||||||
|
|
||||||
int wait_for_terminate(pid_t pid, siginfo_t *status);
|
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) {
|
static int target_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
|
||||||
Target *s = TARGET(u);
|
Target *s = TARGET(u);
|
||||||
|
|
||||||
assert(s);
|
|
||||||
assert(u);
|
assert(u);
|
||||||
assert(key);
|
assert(key);
|
||||||
assert(value);
|
assert(value);
|
||||||
|
|||||||
@ -2304,8 +2304,8 @@ static int unit_log_resources(Unit *u) {
|
|||||||
message_parts[n_message_parts++] = t;
|
message_parts[n_message_parts++] = t;
|
||||||
|
|
||||||
log_level = raise_level(log_level,
|
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++) {
|
for (CGroupIOAccountingMetric k = 0; k < _CGROUP_IO_ACCOUNTING_METRIC_MAX; k++) {
|
||||||
|
|||||||
@ -91,144 +91,6 @@
|
|||||||
# pragma GCC diagnostic ignored "-Waddress-of-packed-member"
|
# pragma GCC diagnostic ignored "-Waddress-of-packed-member"
|
||||||
#endif
|
#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().
|
/* 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
|
* 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(). */
|
* journal_file_set_offline() and journal_file_set_online(). */
|
||||||
@ -255,11 +117,6 @@ static void journal_file_set_offline_internal(JournalFile *f) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case OFFLINE_SYNCING:
|
case OFFLINE_SYNCING:
|
||||||
if (f->archive) {
|
|
||||||
(void) journal_file_truncate(f);
|
|
||||||
(void) journal_file_punch_holes(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
(void) fsync(f->fd);
|
(void) fsync(f->fd);
|
||||||
|
|
||||||
if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_SYNCING, OFFLINE_OFFLINING))
|
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;
|
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(
|
static uint64_t journal_file_entry_seqnum(
|
||||||
JournalFile *f,
|
JournalFile *f,
|
||||||
uint64_t *seqnum) {
|
uint64_t *seqnum) {
|
||||||
@ -1232,7 +1030,7 @@ int journal_file_append_object(
|
|||||||
|
|
||||||
int r;
|
int r;
|
||||||
uint64_t p;
|
uint64_t p;
|
||||||
Object *o;
|
Object *tail, *o;
|
||||||
void *t;
|
void *t;
|
||||||
|
|
||||||
assert(f);
|
assert(f);
|
||||||
@ -1244,10 +1042,27 @@ int journal_file_append_object(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = journal_file_tail_end(f, &p);
|
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)
|
if (r < 0)
|
||||||
return r;
|
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);
|
r = journal_file_allocate(f, p, size);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@ -202,7 +202,6 @@ static inline bool VALID_EPOCH(uint64_t u) {
|
|||||||
FLAGS_SET(le32toh((h)->incompatible_flags), HEADER_INCOMPATIBLE_KEYED_HASH)
|
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_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_n_items(Object *o) _pure_;
|
||||||
uint64_t journal_file_entry_array_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;
|
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) {
|
static int dhcp6_pd_prepare(Link *link) {
|
||||||
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
|
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
|
||||||
return 0;
|
return 0;
|
||||||
@ -583,7 +624,7 @@ static int dhcp6_pd_prepare(Link *link) {
|
|||||||
link_mark_addresses(link, NETWORK_CONFIG_SOURCE_DHCP6PD, NULL);
|
link_mark_addresses(link, NETWORK_CONFIG_SOURCE_DHCP6PD, NULL);
|
||||||
link_mark_routes(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) {
|
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))
|
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
|
||||||
return 0;
|
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) {
|
if (link->dhcp6_pd_messages == 0) {
|
||||||
link->dhcp6_pd_configured = false;
|
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;
|
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) {
|
static int dhcp6_pd_assign_prefixes(Link *link, Link *uplink) {
|
||||||
usec_t timestamp_usec;
|
usec_t timestamp_usec;
|
||||||
int r;
|
int r;
|
||||||
@ -754,14 +898,17 @@ static int dhcp6_pd_assign_prefixes(Link *link, Link *uplink) {
|
|||||||
assert(uplink);
|
assert(uplink);
|
||||||
assert(uplink->dhcp6_lease);
|
assert(uplink->dhcp6_lease);
|
||||||
|
|
||||||
r = dhcp6_pd_prepare(link);
|
/* This is similar to dhcp6_pd_prefix_acquired(), but called when a downstream interface
|
||||||
if (r <= 0)
|
* appears later or reconfiguring the interface. */
|
||||||
return r;
|
|
||||||
|
|
||||||
r = sd_dhcp6_lease_get_timestamp(uplink->dhcp6_lease, clock_boottime_or_monotonic(), ×tamp_usec);
|
r = sd_dhcp6_lease_get_timestamp(uplink->dhcp6_lease, clock_boottime_or_monotonic(), ×tamp_usec);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
r = dhcp6_pd_prepare(link);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
for (sd_dhcp6_lease_reset_pd_prefix_iter(uplink->dhcp6_lease);;) {
|
for (sd_dhcp6_lease_reset_pd_prefix_iter(uplink->dhcp6_lease);;) {
|
||||||
uint32_t lifetime_preferred_sec, lifetime_valid_sec;
|
uint32_t lifetime_preferred_sec, lifetime_valid_sec;
|
||||||
usec_t lifetime_preferred_usec, lifetime_valid_usec;
|
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)
|
if (r < 0)
|
||||||
break;
|
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)
|
if (pd_prefix_len > 64)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -781,76 +931,14 @@ static int dhcp6_pd_assign_prefixes(Link *link, Link *uplink) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
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);
|
r = dhcp6_pd_assign_prefix(link, &pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dhcp6_pd_finalize(link);
|
r = 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);
|
|
||||||
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)
|
if (r < 0)
|
||||||
return r;
|
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 0;
|
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) {
|
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++) {
|
for (unsigned j = 0; j < n_dns; j++) {
|
||||||
const char *str;
|
const char *str;
|
||||||
|
|
||||||
@ -423,45 +418,6 @@ static void serialize_addresses(
|
|||||||
fputc('\n', f);
|
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) {
|
int link_save(Link *link) {
|
||||||
const char *admin_state, *oper_state, *carrier_state, *address_state, *ipv4_address_state, *ipv6_address_state;
|
const char *admin_state, *oper_state, *carrier_state, *address_state, *ipv4_address_state, *ipv6_address_state;
|
||||||
_cleanup_(unlink_and_freep) char *temp_path = NULL;
|
_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);
|
admin_state, oper_state, carrier_state, address_state, ipv4_address_state, ipv6_address_state);
|
||||||
|
|
||||||
if (link->network) {
|
if (link->network) {
|
||||||
const char *online_state;
|
char **dhcp6_domains = NULL, **dhcp_domains = NULL;
|
||||||
|
const char *dhcp_domainname = NULL, *online_state, *p;
|
||||||
bool space;
|
bool space;
|
||||||
|
|
||||||
online_state = link_online_state_to_string(link->online_state);
|
online_state = link_online_state_to_string(link->online_state);
|
||||||
@ -540,14 +497,11 @@ int link_save(Link *link) {
|
|||||||
|
|
||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
|
||||||
/* Make sure to flush out old entries before we use the NDisc data */
|
|
||||||
ndisc_vacuum(link);
|
|
||||||
|
|
||||||
fputs("DNS=", f);
|
fputs("DNS=", f);
|
||||||
if (link->n_dns != UINT_MAX)
|
|
||||||
link_save_dns(link, f, link->dns, link->n_dns, NULL);
|
|
||||||
else {
|
|
||||||
space = false;
|
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);
|
link_save_dns(link, f, link->network->dns, link->network->n_dns, &space);
|
||||||
|
|
||||||
serialize_addresses(f, NULL, &space,
|
serialize_addresses(f, NULL, &space,
|
||||||
@ -560,25 +514,22 @@ int link_save(Link *link) {
|
|||||||
sd_dhcp6_lease_get_dns,
|
sd_dhcp6_lease_get_dns,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (link->network->ipv6_accept_ra_use_dns) {
|
/* Make sure to flush out old entries before we use the NDisc data */
|
||||||
|
ndisc_vacuum(link);
|
||||||
|
|
||||||
|
if (link->network->ipv6_accept_ra_use_dns && link->ndisc_rdnss) {
|
||||||
NDiscRDNSS *dd;
|
NDiscRDNSS *dd;
|
||||||
|
|
||||||
SET_FOREACH(dd, link->ndisc_rdnss)
|
SET_FOREACH(dd, link->ndisc_rdnss)
|
||||||
serialize_in6_addrs(f, &dd->address, 1, &space);
|
serialize_in6_addrs(f, &dd->address, 1, &space);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fputc('\n', f);
|
fputc('\n', f);
|
||||||
|
|
||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
|
||||||
if (link->ntp) {
|
|
||||||
fputs("NTP=", f);
|
|
||||||
fputstrv(f, link->ntp, NULL, NULL);
|
|
||||||
fputc('\n', f);
|
|
||||||
} else
|
|
||||||
serialize_addresses(f, "NTP", NULL,
|
serialize_addresses(f, "NTP", NULL,
|
||||||
link->network->ntp,
|
link->ntp ?: link->network->ntp,
|
||||||
link->dhcp_lease,
|
link->dhcp_lease,
|
||||||
link->network->dhcp_use_ntp,
|
link->network->dhcp_use_ntp,
|
||||||
SD_DHCP_LEASE_NTP,
|
SD_DHCP_LEASE_NTP,
|
||||||
@ -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);
|
fputs("DOMAINS=", f);
|
||||||
if (link->search_domains)
|
space = false;
|
||||||
link_save_domains(link, f, link->search_domains, DHCP_USE_DOMAINS_NO);
|
ORDERED_SET_FOREACH(p, link->search_domains ?: link->network->search_domains)
|
||||||
else
|
fputs_with_space(f, p, NULL, &space);
|
||||||
link_save_domains(link, f, link->network->search_domains, DHCP_USE_DOMAINS_YES);
|
|
||||||
|
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);
|
fputc('\n', f);
|
||||||
|
|
||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
|
||||||
fputs("ROUTE_DOMAINS=", f);
|
fputs("ROUTE_DOMAINS=", f);
|
||||||
if (link->route_domains)
|
space = false;
|
||||||
link_save_domains(link, f, link->route_domains, DHCP_USE_DOMAINS_NO);
|
ORDERED_SET_FOREACH(p, link->route_domains ?: link->network->route_domains)
|
||||||
else
|
fputs_with_space(f, p, NULL, &space);
|
||||||
link_save_domains(link, f, link->network->route_domains, DHCP_USE_DOMAINS_ROUTE);
|
|
||||||
|
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);
|
fputc('\n', f);
|
||||||
|
|
||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
|||||||
@ -170,7 +170,7 @@ int dns_answer_add(
|
|||||||
/* Entry already exists, keep the entry with the higher TTL. */
|
/* Entry already exists, keep the entry with the higher TTL. */
|
||||||
if (rr->ttl > exist->rr->ttl) {
|
if (rr->ttl > exist->rr->ttl) {
|
||||||
dns_resource_record_unref(exist->rr);
|
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 */
|
/* Update RRSIG and RR at the same time */
|
||||||
if (rrsig) {
|
if (rrsig) {
|
||||||
|
|||||||
@ -484,8 +484,8 @@ TEST(get_process_cmdline_harder) {
|
|||||||
/* Test with multiple arguments that do require quoting */
|
/* Test with multiple arguments that do require quoting */
|
||||||
|
|
||||||
#define CMDLINE1 "foo\0'bar'\0\"bar$\"\0x y z\0!``\0"
|
#define CMDLINE1 "foo\0'bar'\0\"bar$\"\0x y z\0!``\0"
|
||||||
#define EXPECT1 "foo \"'bar'\" \"\\\"bar\\$\\\"\" \"x y z\" \"!\\`\\`\""
|
#define EXPECT1 "foo \"'bar'\" \"\\\"bar\\$\\\"\" \"x y z\" \"!\\`\\`\" \"\""
|
||||||
#define EXPECT1p "foo $'\\'bar\\'' $'\"bar$\"' $'x y z' $'!``'"
|
#define EXPECT1p "foo $'\\'bar\\'' $'\"bar$\"' $'x y z' $'!``' \"\""
|
||||||
assert_se(lseek(fd, SEEK_SET, 0) == 0);
|
assert_se(lseek(fd, SEEK_SET, 0) == 0);
|
||||||
assert_se(write(fd, CMDLINE1, sizeof CMDLINE1) == sizeof CMDLINE1);
|
assert_se(write(fd, CMDLINE1, sizeof CMDLINE1) == sizeof CMDLINE1);
|
||||||
assert_se(ftruncate(fd, sizeof CMDLINE1) == 0);
|
assert_se(ftruncate(fd, sizeof CMDLINE1) == 0);
|
||||||
@ -503,8 +503,8 @@ TEST(get_process_cmdline_harder) {
|
|||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
#define CMDLINE2 "foo\0\1\2\3\0\0"
|
#define CMDLINE2 "foo\0\1\2\3\0\0"
|
||||||
#define EXPECT2 "foo \"\\001\\002\\003\""
|
#define EXPECT2 "foo \"\\001\\002\\003\" \"\" \"\""
|
||||||
#define EXPECT2p "foo $'\\001\\002\\003'"
|
#define EXPECT2p "foo $'\\001\\002\\003' \"\" \"\""
|
||||||
assert_se(lseek(fd, SEEK_SET, 0) == 0);
|
assert_se(lseek(fd, SEEK_SET, 0) == 0);
|
||||||
assert_se(write(fd, CMDLINE2, sizeof CMDLINE2) == sizeof CMDLINE2);
|
assert_se(write(fd, CMDLINE2, sizeof CMDLINE2) == sizeof CMDLINE2);
|
||||||
assert_se(ftruncate(fd, sizeof CMDLINE2) == 0);
|
assert_se(ftruncate(fd, sizeof CMDLINE2) == 0);
|
||||||
|
|||||||
@ -175,6 +175,7 @@ BASICTOOLS=(
|
|||||||
sfdisk
|
sfdisk
|
||||||
sh
|
sh
|
||||||
sleep
|
sleep
|
||||||
|
socat
|
||||||
stat
|
stat
|
||||||
su
|
su
|
||||||
sulogin
|
sulogin
|
||||||
|
|||||||
@ -7,7 +7,8 @@ ExecStartPre=rm -f /failed /testok
|
|||||||
Type=oneshot
|
Type=oneshot
|
||||||
ExecStart=rm -f /tmp/nonexistent
|
ExecStart=rm -f /tmp/nonexistent
|
||||||
ExecStart=systemctl start test10.socket
|
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
|
# TriggerLimitIntervalSec= by default is set to 2s. A "sleep 10" should give
|
||||||
# systemd enough time even on slower machines, to reach the trigger limit.
|
# systemd enough time even on slower machines, to reach the trigger limit.
|
||||||
ExecStart=sleep 10
|
ExecStart=sleep 10
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user