systemd: merge branch systemd into master
This commit is contained in:
@@ -30,6 +30,17 @@
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* systemd detects whether compiler supports "-Wstringop-truncation" to disable
|
||||
* the warning at particular places. Since we anyway build with -Wno-pragma,
|
||||
* we don't do that and just let systemd call
|
||||
*
|
||||
* _Pragma("GCC diagnostic ignored \"-Wstringop-truncation\"")
|
||||
*
|
||||
* regadless whether that would result in a -Wpragma warning. */
|
||||
#define HAVE_WSTRINGOP_TRUNCATION 1
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline int
|
||||
_nm_log_get_max_level_realm (void)
|
||||
{
|
||||
@@ -86,6 +97,14 @@ G_STMT_START { \
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* systemd cannot be compiled with "-Wdeclaration-after-statement". In particular
|
||||
* in combintation with assert_cc(). */
|
||||
NM_PRAGMA_WARNING_DISABLE ("-Wdeclaration-after-statement")
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline pid_t
|
||||
raw_getpid (void) {
|
||||
#if defined(__alpha__)
|
||||
|
@@ -66,8 +66,31 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
|
||||
if (!q)
|
||||
return NULL;
|
||||
|
||||
if (size > 0) {
|
||||
size_t bn;
|
||||
|
||||
/* Adjust for the 64 byte minimum */
|
||||
newalloc = a / size;
|
||||
|
||||
bn = malloc_usable_size(q) / size;
|
||||
if (bn > newalloc) {
|
||||
void *qq;
|
||||
|
||||
/* The actual size allocated is larger than what we asked for. Let's call realloc() again to
|
||||
* take possession of the extra space. This should be cheap, since libc doesn't have to move
|
||||
* the memory for this. */
|
||||
|
||||
qq = realloc(q, bn * size);
|
||||
if (_likely_(qq)) {
|
||||
*p = qq;
|
||||
*allocated = bn;
|
||||
return qq;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*p = q;
|
||||
*allocated = _unlikely_(size == 0) ? newalloc : malloc_usable_size(q) / size;
|
||||
*allocated = newalloc;
|
||||
return q;
|
||||
}
|
||||
|
||||
|
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "nm-sd-adapt-shared.h"
|
||||
|
||||
#include <stdio_ext.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "env-file.h"
|
||||
#include "env-util.h"
|
||||
@@ -548,7 +546,6 @@ int write_env_file(const char *fname, char **l) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
(void) fchmod_umask(fileno(f), 0644);
|
||||
|
||||
STRV_FOREACH(i, l)
|
||||
|
@@ -31,6 +31,52 @@
|
||||
|
||||
#define READ_FULL_BYTES_MAX (4U*1024U*1024U)
|
||||
|
||||
int fopen_unlocked(const char *path, const char *options, FILE **ret) {
|
||||
assert(ret);
|
||||
|
||||
FILE *f = fopen(path, options);
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
*ret = f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fdopen_unlocked(int fd, const char *options, FILE **ret) {
|
||||
assert(ret);
|
||||
|
||||
FILE *f = fdopen(fd, options);
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
*ret = f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
FILE* open_memstream_unlocked(char **ptr, size_t *sizeloc) {
|
||||
FILE *f = open_memstream(ptr, sizeloc);
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
FILE* fmemopen_unlocked(void *buf, size_t size, const char *mode) {
|
||||
FILE *f = fmemopen(buf, size, mode);
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
int write_string_stream_ts(
|
||||
FILE *f,
|
||||
@@ -98,7 +144,6 @@ static int write_string_file_atomic(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
(void) fchmod_umask(fileno(f), 0644);
|
||||
|
||||
r = write_string_stream_ts(f, line, flags, ts);
|
||||
@@ -144,11 +189,9 @@ int write_string_file_ts(
|
||||
assert(!ts);
|
||||
|
||||
if (flags & WRITE_STRING_FILE_CREATE) {
|
||||
f = fopen(fn, "we");
|
||||
if (!f) {
|
||||
r = -errno;
|
||||
r = fopen_unlocked(fn, "we", &f);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
int fd;
|
||||
|
||||
@@ -160,16 +203,13 @@ int write_string_file_ts(
|
||||
goto fail;
|
||||
}
|
||||
|
||||
f = fdopen(fd, "w");
|
||||
if (!f) {
|
||||
r = -errno;
|
||||
r = fdopen_unlocked(fd, "w", &f);
|
||||
if (r < 0) {
|
||||
safe_close(fd);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
if (flags & WRITE_STRING_FILE_DISABLE_BUFFER)
|
||||
setvbuf(f, NULL, _IONBF, 0);
|
||||
|
||||
@@ -216,15 +256,14 @@ int write_string_filef(
|
||||
|
||||
int read_one_line_file(const char *fn, char **line) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
int r;
|
||||
|
||||
assert(fn);
|
||||
assert(line);
|
||||
|
||||
f = fopen(fn, "re");
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
r = fopen_unlocked(fn, "re", &f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return read_line(f, LONG_LINE_MAX, line);
|
||||
}
|
||||
@@ -233,6 +272,7 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
size_t l, k;
|
||||
int r;
|
||||
|
||||
assert(fn);
|
||||
assert(blob);
|
||||
@@ -246,11 +286,9 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
f = fopen(fn, "re");
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
r = fopen_unlocked(fn, "re", &f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* We try to read one byte more than we need, so that we know whether we hit eof */
|
||||
errno = 0;
|
||||
@@ -283,7 +321,8 @@ int read_full_stream_full(
|
||||
|
||||
assert(f);
|
||||
assert(ret_contents);
|
||||
assert(!(flags & READ_FULL_FILE_UNBASE64) || ret_size);
|
||||
assert(!FLAGS_SET(flags, READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX));
|
||||
assert(!(flags & (READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX)) || ret_size);
|
||||
|
||||
n_next = LINE_MAX; /* Start size */
|
||||
|
||||
@@ -324,6 +363,7 @@ int read_full_stream_full(
|
||||
}
|
||||
memcpy_safe(t, buf, n);
|
||||
explicit_bzero_safe(buf, n);
|
||||
buf = mfree(buf);
|
||||
} else {
|
||||
t = realloc(buf, n_next + 1);
|
||||
if (!t)
|
||||
@@ -360,9 +400,12 @@ int read_full_stream_full(
|
||||
n_next = MIN(n * 2, READ_FULL_BYTES_MAX);
|
||||
}
|
||||
|
||||
if (flags & READ_FULL_FILE_UNBASE64) {
|
||||
if (flags & (READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX)) {
|
||||
buf[l++] = 0;
|
||||
r = unbase64mem_full(buf, l, flags & READ_FULL_FILE_SECURE, (void **) ret_contents, ret_size);
|
||||
if (flags & READ_FULL_FILE_UNBASE64)
|
||||
r = unbase64mem_full(buf, l, flags & READ_FULL_FILE_SECURE, (void **) ret_contents, ret_size);
|
||||
else
|
||||
r = unhexmem_full(buf, l, flags & READ_FULL_FILE_SECURE, (void **) ret_contents, ret_size);
|
||||
goto finalize;
|
||||
}
|
||||
|
||||
@@ -394,15 +437,14 @@ finalize:
|
||||
|
||||
int read_full_file_full(const char *filename, ReadFullFileFlags flags, char **contents, size_t *size) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(contents);
|
||||
|
||||
f = fopen(filename, "re");
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
r = fopen_unlocked(filename, "re", &f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return read_full_stream_full(f, filename, flags, contents, size);
|
||||
}
|
||||
|
@@ -31,8 +31,14 @@ typedef enum {
|
||||
typedef enum {
|
||||
READ_FULL_FILE_SECURE = 1 << 0,
|
||||
READ_FULL_FILE_UNBASE64 = 1 << 1,
|
||||
READ_FULL_FILE_UNHEX = 1 << 2,
|
||||
} ReadFullFileFlags;
|
||||
|
||||
int fopen_unlocked(const char *path, const char *options, FILE **ret);
|
||||
int fdopen_unlocked(int fd, const char *options, FILE **ret);
|
||||
FILE* open_memstream_unlocked(char **ptr, size_t *sizeloc);
|
||||
FILE* fmemopen_unlocked(void *buf, size_t size, const char *mode);
|
||||
|
||||
int write_string_stream_ts(FILE *f, const char *line, WriteStringFileFlags flags, struct timespec *ts);
|
||||
static inline int write_string_stream(FILE *f, const char *line, WriteStringFileFlags flags) {
|
||||
return write_string_stream_ts(f, line, flags, NULL);
|
||||
|
@@ -110,10 +110,12 @@ static int unhex_next(const char **p, size_t *l) {
|
||||
return r;
|
||||
}
|
||||
|
||||
int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) {
|
||||
int unhexmem_full(const char *p, size_t l, bool secure, void **ret, size_t *ret_len) {
|
||||
_cleanup_free_ uint8_t *buf = NULL;
|
||||
size_t buf_size;
|
||||
const char *x;
|
||||
uint8_t *z;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
assert(ret_len);
|
||||
@@ -123,7 +125,8 @@ int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) {
|
||||
l = strlen(p);
|
||||
|
||||
/* Note that the calculation of memory size is an upper boundary, as we ignore whitespace while decoding */
|
||||
buf = malloc((l + 1) / 2 + 1);
|
||||
buf_size = (l + 1) / 2 + 1;
|
||||
buf = malloc(buf_size);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -133,12 +136,16 @@ int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) {
|
||||
a = unhex_next(&x, &l);
|
||||
if (a == -EPIPE) /* End of string */
|
||||
break;
|
||||
if (a < 0)
|
||||
return a;
|
||||
if (a < 0) {
|
||||
r = a;
|
||||
goto on_failure;
|
||||
}
|
||||
|
||||
b = unhex_next(&x, &l);
|
||||
if (b < 0)
|
||||
return b;
|
||||
if (b < 0) {
|
||||
r = b;
|
||||
goto on_failure;
|
||||
}
|
||||
|
||||
*(z++) = (uint8_t) a << 4 | (uint8_t) b;
|
||||
}
|
||||
@@ -149,6 +156,12 @@ int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) {
|
||||
*ret = TAKE_PTR(buf);
|
||||
|
||||
return 0;
|
||||
|
||||
on_failure:
|
||||
if (secure)
|
||||
explicit_bzero_safe(buf, buf_size);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
|
@@ -18,7 +18,10 @@ char hexchar(int x) _const_;
|
||||
int unhexchar(char c) _const_;
|
||||
|
||||
char *hexmem(const void *p, size_t l);
|
||||
int unhexmem(const char *p, size_t l, void **mem, size_t *len);
|
||||
int unhexmem_full(const char *p, size_t l, bool secure, void **mem, size_t *len);
|
||||
static inline int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
|
||||
return unhexmem_full(p, l, false, mem, len);
|
||||
}
|
||||
|
||||
char base32hexchar(int x) _const_;
|
||||
int unbase32hexchar(char c) _const_;
|
||||
|
@@ -106,6 +106,15 @@
|
||||
_Pragma("GCC diagnostic push"); \
|
||||
_Pragma("GCC diagnostic ignored \"-Wincompatible-pointer-types\"")
|
||||
|
||||
#if HAVE_WSTRINGOP_TRUNCATION
|
||||
# define DISABLE_WARNING_STRINGOP_TRUNCATION \
|
||||
_Pragma("GCC diagnostic push"); \
|
||||
_Pragma("GCC diagnostic ignored \"-Wstringop-truncation\"")
|
||||
#else
|
||||
# define DISABLE_WARNING_STRINGOP_TRUNCATION \
|
||||
_Pragma("GCC diagnostic push")
|
||||
#endif
|
||||
|
||||
#define REENABLE_WARNING \
|
||||
_Pragma("GCC diagnostic pop")
|
||||
#else
|
||||
|
@@ -10,7 +10,6 @@
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
@@ -111,7 +110,7 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
|
||||
char *k;
|
||||
_cleanup_free_ char *ans = NULL;
|
||||
const char *p;
|
||||
int c;
|
||||
int c, r;
|
||||
|
||||
assert(line);
|
||||
assert(pid >= 0);
|
||||
@@ -126,15 +125,11 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
|
||||
* comm_fallback is false). Returns 0 and sets *line otherwise. */
|
||||
|
||||
p = procfs_file_alloca(pid, "cmdline");
|
||||
|
||||
f = fopen(p, "re");
|
||||
if (!f) {
|
||||
if (errno == ENOENT)
|
||||
return -ESRCH;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
r = fopen_unlocked(p, "re", &f);
|
||||
if (r == -ENOENT)
|
||||
return -ESRCH;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (max_length == 0) {
|
||||
/* This is supposed to be a safety guard against runaway command lines. */
|
||||
@@ -518,14 +513,11 @@ static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
|
||||
return -EINVAL;
|
||||
|
||||
p = procfs_file_alloca(pid, "status");
|
||||
f = fopen(p, "re");
|
||||
if (!f) {
|
||||
if (errno == ENOENT)
|
||||
return -ESRCH;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
r = fopen_unlocked(p, "re", &f);
|
||||
if (r == -ENOENT)
|
||||
return -ESRCH;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
@@ -607,14 +599,11 @@ int get_process_environ(pid_t pid, char **env) {
|
||||
|
||||
p = procfs_file_alloca(pid, "environ");
|
||||
|
||||
f = fopen(p, "re");
|
||||
if (!f) {
|
||||
if (errno == ENOENT)
|
||||
return -ESRCH;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
r = fopen_unlocked(p, "re", &f);
|
||||
if (r == -ENOENT)
|
||||
return -ESRCH;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
for (;;) {
|
||||
char c;
|
||||
@@ -900,15 +889,11 @@ int getenv_for_pid(pid_t pid, const char *field, char **ret) {
|
||||
|
||||
path = procfs_file_alloca(pid, "environ");
|
||||
|
||||
f = fopen(path, "re");
|
||||
if (!f) {
|
||||
if (errno == ENOENT)
|
||||
return -ESRCH;
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
r = fopen_unlocked(path, "re", &f);
|
||||
if (r == -ENOENT)
|
||||
return -ESRCH;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
l = strlen(field);
|
||||
for (;;) {
|
||||
|
@@ -30,13 +30,15 @@
|
||||
#include "io-util.h"
|
||||
#include "missing.h"
|
||||
#include "random-util.h"
|
||||
#include "siphash24.h"
|
||||
#include "time-util.h"
|
||||
|
||||
int rdrand(unsigned long *ret) {
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
static int have_rdrand = -1;
|
||||
unsigned char err;
|
||||
unsigned long v;
|
||||
uint8_t success;
|
||||
|
||||
if (have_rdrand < 0) {
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
@@ -47,7 +49,12 @@ int rdrand(unsigned long *ret) {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
have_rdrand = !!(ecx & (1U << 30));
|
||||
/* Compat with old gcc where bit_RDRND didn't exist yet */
|
||||
#ifndef bit_RDRND
|
||||
#define bit_RDRND (1U << 30)
|
||||
#endif
|
||||
|
||||
have_rdrand = !!(ecx & bit_RDRND);
|
||||
}
|
||||
|
||||
if (have_rdrand == 0)
|
||||
@@ -55,12 +62,24 @@ int rdrand(unsigned long *ret) {
|
||||
|
||||
asm volatile("rdrand %0;"
|
||||
"setc %1"
|
||||
: "=r" (*ret),
|
||||
"=qm" (err));
|
||||
msan_unpoison(&err, sizeof(err));
|
||||
if (!err)
|
||||
: "=r" (v),
|
||||
"=qm" (success));
|
||||
msan_unpoison(&success, sizeof(success));
|
||||
if (!success)
|
||||
return -EAGAIN;
|
||||
|
||||
/* Apparently on some AMD CPUs RDRAND will sometimes (after a suspend/resume cycle?) report success
|
||||
* via the carry flag but nonetheless return the same fixed value -1 in all cases. This appears to be
|
||||
* a bad bug in the CPU or firmware. Let's deal with that and work-around this by explicitly checking
|
||||
* for this special value (and also 0, just to be sure) and filtering it out. This is a work-around
|
||||
* only however and something AMD really should fix properly. The Linux kernel should probably work
|
||||
* around this issue by turning off RDRAND altogether on those CPUs. See:
|
||||
* https://github.com/systemd/systemd/issues/11810 */
|
||||
if (v == 0 || v == ULONG_MAX)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN),
|
||||
"RDRAND returned suspicious value %lx, assuming bad hardware RNG, not using value.", v);
|
||||
|
||||
*ret = v;
|
||||
return 0;
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
@@ -73,21 +92,22 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
|
||||
bool got_some = false;
|
||||
int r;
|
||||
|
||||
/* Gathers some randomness from the kernel (or the CPU if the RANDOM_ALLOW_RDRAND flag is set). This call won't
|
||||
* block, unless the RANDOM_BLOCK flag is set. If RANDOM_DONT_DRAIN is set, an error is returned if the random
|
||||
* pool is not initialized. Otherwise it will always return some data from the kernel, regardless of whether
|
||||
* the random pool is fully initialized or not. */
|
||||
/* Gathers some randomness from the kernel (or the CPU if the RANDOM_ALLOW_RDRAND flag is set). This
|
||||
* call won't block, unless the RANDOM_BLOCK flag is set. If RANDOM_MAY_FAIL is set, an error is
|
||||
* returned if the random pool is not initialized. Otherwise it will always return some data from the
|
||||
* kernel, regardless of whether the random pool is fully initialized or not. */
|
||||
|
||||
if (n == 0)
|
||||
return 0;
|
||||
|
||||
if (FLAGS_SET(flags, RANDOM_ALLOW_RDRAND))
|
||||
/* Try x86-64' RDRAND intrinsic if we have it. We only use it if high quality randomness is not
|
||||
* required, as we don't trust it (who does?). Note that we only do a single iteration of RDRAND here,
|
||||
* even though the Intel docs suggest calling this in a tight loop of 10 invocations or so. That's
|
||||
* because we don't really care about the quality here. We generally prefer using RDRAND if the caller
|
||||
* allows us too, since this way we won't drain the kernel randomness pool if we don't need it, as the
|
||||
* pool's entropy is scarce. */
|
||||
/* Try x86-64' RDRAND intrinsic if we have it. We only use it if high quality randomness is
|
||||
* not required, as we don't trust it (who does?). Note that we only do a single iteration of
|
||||
* RDRAND here, even though the Intel docs suggest calling this in a tight loop of 10
|
||||
* invocations or so. That's because we don't really care about the quality here. We
|
||||
* generally prefer using RDRAND if the caller allows us to, since this way we won't upset
|
||||
* the kernel's random subsystem by accessing it before the pool is initialized (after all it
|
||||
* will kmsg log about every attempt to do so)..*/
|
||||
for (;;) {
|
||||
unsigned long u;
|
||||
size_t m;
|
||||
@@ -162,12 +182,13 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
|
||||
break;
|
||||
|
||||
} else if (errno == EAGAIN) {
|
||||
/* The kernel has no entropy whatsoever. Let's remember to use the syscall the next
|
||||
* time again though.
|
||||
/* The kernel has no entropy whatsoever. Let's remember to use the syscall
|
||||
* the next time again though.
|
||||
*
|
||||
* If RANDOM_DONT_DRAIN is set, return an error so that random_bytes() can produce some
|
||||
* pseudo-random bytes instead. Otherwise, fall back to /dev/urandom, which we know is empty,
|
||||
* but the kernel will produce some bytes for us on a best-effort basis. */
|
||||
* If RANDOM_MAY_FAIL is set, return an error so that random_bytes() can
|
||||
* produce some pseudo-random bytes instead. Otherwise, fall back to
|
||||
* /dev/urandom, which we know is empty, but the kernel will produce some
|
||||
* bytes for us on a best-effort basis. */
|
||||
have_syscall = true;
|
||||
|
||||
if (got_some && FLAGS_SET(flags, RANDOM_EXTEND_WITH_PSEUDO)) {
|
||||
@@ -176,7 +197,7 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(flags, RANDOM_DONT_DRAIN))
|
||||
if (FLAGS_SET(flags, RANDOM_MAY_FAIL))
|
||||
return -ENODATA;
|
||||
|
||||
/* Use /dev/urandom instead */
|
||||
@@ -205,14 +226,19 @@ void initialize_srand(void) {
|
||||
return;
|
||||
|
||||
#if HAVE_SYS_AUXV_H
|
||||
/* The kernel provides us with 16 bytes of entropy in auxv, so let's
|
||||
* try to make use of that to seed the pseudo-random generator. It's
|
||||
* better than nothing... */
|
||||
/* The kernel provides us with 16 bytes of entropy in auxv, so let's try to make use of that to seed
|
||||
* the pseudo-random generator. It's better than nothing... But let's first hash it to make it harder
|
||||
* to recover the original value by watching any pseudo-random bits we generate. After all the
|
||||
* AT_RANDOM data might be used by other stuff too (in particular: ASLR), and we probably shouldn't
|
||||
* leak the seed for that. */
|
||||
|
||||
auxv = (const void*) getauxval(AT_RANDOM);
|
||||
auxv = ULONG_TO_PTR(getauxval(AT_RANDOM));
|
||||
if (auxv) {
|
||||
assert_cc(sizeof(x) <= 16);
|
||||
memcpy(&x, auxv, sizeof(x));
|
||||
static const uint8_t auxval_hash_key[16] = {
|
||||
0x92, 0x6e, 0xfe, 0x1b, 0xcf, 0x00, 0x52, 0x9c, 0xcc, 0x42, 0xcf, 0xdc, 0x94, 0x1f, 0x81, 0x0f
|
||||
};
|
||||
|
||||
x = (unsigned) siphash24(auxv, 16, auxval_hash_key);
|
||||
} else
|
||||
#endif
|
||||
x = 0;
|
||||
@@ -259,7 +285,7 @@ void pseudo_random_bytes(void *p, size_t n) {
|
||||
|
||||
void random_bytes(void *p, size_t n) {
|
||||
|
||||
if (genuine_random_bytes(p, n, RANDOM_EXTEND_WITH_PSEUDO|RANDOM_DONT_DRAIN|RANDOM_ALLOW_RDRAND) >= 0)
|
||||
if (genuine_random_bytes(p, n, RANDOM_EXTEND_WITH_PSEUDO|RANDOM_MAY_FAIL|RANDOM_ALLOW_RDRAND) >= 0)
|
||||
return;
|
||||
|
||||
/* If for some reason some user made /dev/urandom unavailable to us, or the kernel has no entropy, use a PRNG instead. */
|
||||
|
@@ -8,11 +8,11 @@
|
||||
typedef enum RandomFlags {
|
||||
RANDOM_EXTEND_WITH_PSEUDO = 1 << 0, /* If we can't get enough genuine randomness, but some, fill up the rest with pseudo-randomness */
|
||||
RANDOM_BLOCK = 1 << 1, /* Rather block than return crap randomness (only if the kernel supports that) */
|
||||
RANDOM_DONT_DRAIN = 1 << 2, /* If we can't get any randomness at all, return early with -EAGAIN */
|
||||
RANDOM_MAY_FAIL = 1 << 2, /* If we can't get any randomness at all, return early with -ENODATA */
|
||||
RANDOM_ALLOW_RDRAND = 1 << 3, /* Allow usage of the CPU RNG */
|
||||
} RandomFlags;
|
||||
|
||||
int genuine_random_bytes(void *p, size_t n, RandomFlags flags); /* returns "genuine" randomness, optionally filled upwith pseudo random, if not enough is available */
|
||||
int genuine_random_bytes(void *p, size_t n, RandomFlags flags); /* returns "genuine" randomness, optionally filled up with pseudo random, if not enough is available */
|
||||
void pseudo_random_bytes(void *p, size_t n); /* returns only pseudo-randommess (but possibly seeded from something better) */
|
||||
void random_bytes(void *p, size_t n); /* returns genuine randomness if cheaply available, and pseudo randomness if not. */
|
||||
|
||||
|
@@ -1224,17 +1224,34 @@ fallback:
|
||||
}
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
/* Put a limit on how many times will attempt to call accept4(). We loop
|
||||
* only on "transient" errors, but let's make sure we don't loop forever. */
|
||||
#define MAX_FLUSH_ITERATIONS 1024
|
||||
|
||||
int flush_accept(int fd) {
|
||||
|
||||
struct pollfd pollfd = {
|
||||
.fd = fd,
|
||||
.events = POLLIN,
|
||||
};
|
||||
int r;
|
||||
int r, b;
|
||||
socklen_t l = sizeof(b);
|
||||
|
||||
/* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately closing them. */
|
||||
/* Similar to flush_fd() but flushes all incoming connections by accepting and immediately closing
|
||||
* them. */
|
||||
|
||||
for (;;) {
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &b, &l) < 0)
|
||||
return -errno;
|
||||
|
||||
assert(l == sizeof(b));
|
||||
if (!b) /* Let's check if this socket accepts connections before calling accept(). accept4() can
|
||||
* return EOPNOTSUPP if the fd is not a listening socket, which we should treat as a fatal
|
||||
* error, or in case the incoming TCP connection triggered a network issue, which we want to
|
||||
* treat as a transient error. Thus, let's rule out the first reason for EOPNOTSUPP early, so
|
||||
* we can loop safely on transient errors below. */
|
||||
return -ENOTTY;
|
||||
|
||||
for (unsigned iteration = 0;; iteration++) {
|
||||
int cfd;
|
||||
|
||||
r = poll(&pollfd, 1, 0);
|
||||
@@ -1247,6 +1264,10 @@ int flush_accept(int fd) {
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
if (iteration >= MAX_FLUSH_ITERATIONS)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EBUSY),
|
||||
"Failed to flush connections within " STRINGIFY(MAX_FLUSH_ITERATIONS) " iterations.");
|
||||
|
||||
cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
|
||||
if (cfd < 0) {
|
||||
if (errno == EAGAIN)
|
||||
|
@@ -6,7 +6,6 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -736,6 +735,7 @@ char *strreplace(const char *text, const char *old_string, const char *new_strin
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
static void advance_offsets(ssize_t diff, size_t offsets[static 2], size_t shift[static 2], size_t size) {
|
||||
if (!offsets)
|
||||
return;
|
||||
@@ -767,23 +767,20 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
|
||||
* 2. Strips ANSI color sequences (a subset of CSI), i.e. ESC '[' … 'm' sequences
|
||||
* 3. Strips ANSI operating system sequences (CSO), i.e. ESC ']' … BEL sequences
|
||||
*
|
||||
* Everything else will be left as it is. In particular other ANSI sequences are left as they are, as are any
|
||||
* other special characters. Truncated ANSI sequences are left-as is too. This call is supposed to suppress the
|
||||
* most basic formatting noise, but nothing else.
|
||||
* Everything else will be left as it is. In particular other ANSI sequences are left as they are, as
|
||||
* are any other special characters. Truncated ANSI sequences are left-as is too. This call is
|
||||
* supposed to suppress the most basic formatting noise, but nothing else.
|
||||
*
|
||||
* Why care for CSO sequences? Well, to undo what terminal_urlify() and friends generate. */
|
||||
|
||||
isz = _isz ? *_isz : strlen(*ibuf);
|
||||
|
||||
f = open_memstream(&obuf, &osz);
|
||||
/* Note we turn off internal locking on f for performance reasons. It's safe to do so since we
|
||||
* created f here and it doesn't leave our scope. */
|
||||
f = open_memstream_unlocked(&obuf, &osz);
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
/* Note we turn off internal locking on f for performance reasons. It's safe to do so since we created f here
|
||||
* and it doesn't leave our scope. */
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
for (i = *ibuf; i < *ibuf + isz + 1; i++) {
|
||||
|
||||
switch (state) {
|
||||
@@ -872,7 +869,6 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
|
||||
return obuf;
|
||||
}
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
char *strextend_with_separator(char **x, const char *separator, ...) {
|
||||
bool need_separator;
|
||||
size_t f, l, l_separator;
|
||||
|
@@ -212,6 +212,12 @@ static inline size_t strlen_ptr(const char *s) {
|
||||
return strlen(s);
|
||||
}
|
||||
|
||||
DISABLE_WARNING_STRINGOP_TRUNCATION;
|
||||
static inline void strncpy_exact(char *buf, const char *src, size_t buf_len) {
|
||||
strncpy(buf, src, buf_len);
|
||||
}
|
||||
REENABLE_WARNING;
|
||||
|
||||
/* Like startswith(), but operates on arbitrary memory blocks */
|
||||
static inline void *memory_startswith(const void *p, size_t sz, const char *token) {
|
||||
size_t n;
|
||||
|
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "macro.h"
|
||||
@@ -39,12 +40,15 @@ int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
f = fdopen(fd, "w");
|
||||
if (!f) {
|
||||
unlink_noerrno(t);
|
||||
/* This assumes that returned FILE object is short-lived and used within the same single-threaded
|
||||
* context and never shared externally, hence locking is not necessary. */
|
||||
|
||||
r = fdopen_unlocked(fd, "w", &f);
|
||||
if (r < 0) {
|
||||
unlink(t);
|
||||
free(t);
|
||||
safe_close(fd);
|
||||
return -errno;
|
||||
return r;
|
||||
}
|
||||
|
||||
*_f = f;
|
||||
|
@@ -8,21 +8,19 @@
|
||||
#include "macro.h"
|
||||
|
||||
static inline void umaskp(mode_t *u) {
|
||||
umask(*u);
|
||||
umask(*u & 0777);
|
||||
}
|
||||
|
||||
#define _cleanup_umask_ _cleanup_(umaskp)
|
||||
|
||||
struct _umask_struct_ {
|
||||
mode_t mask;
|
||||
bool quit;
|
||||
};
|
||||
/* We make use of the fact here that the umask() concept is using only the lower 9 bits of mode_t, although
|
||||
* mode_t has space for the file type in the bits further up. We simply OR in the file type mask S_IFMT to
|
||||
* distinguish the first and the second iteration of the RUN_WITH_UMASK() loop, so that we can run the first
|
||||
* one, and exit on the second. */
|
||||
|
||||
static inline void _reset_umask_(struct _umask_struct_ *s) {
|
||||
umask(s->mask);
|
||||
};
|
||||
assert_cc((S_IFMT & 0777) == 0);
|
||||
|
||||
#define RUN_WITH_UMASK(mask) \
|
||||
for (_cleanup_(_reset_umask_) struct _umask_struct_ _saved_umask_ = { umask(mask), false }; \
|
||||
!_saved_umask_.quit ; \
|
||||
_saved_umask_.quit = true)
|
||||
for (_cleanup_umask_ mode_t _saved_umask_ = umask(mask) | S_IFMT; \
|
||||
FLAGS_SET(_saved_umask_, S_IFMT); \
|
||||
_saved_umask_ &= 0777)
|
||||
|
@@ -636,13 +636,13 @@ bound4_handle (NMDhcpSystemd *self)
|
||||
options);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
dhcp_event_cb (sd_dhcp_client *client, int event, gpointer user_data)
|
||||
{
|
||||
NMDhcpSystemd *self = NM_DHCP_SYSTEMD (user_data);
|
||||
NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (self);
|
||||
|
||||
g_assert (priv->client4 == client);
|
||||
nm_assert (priv->client4 == client);
|
||||
|
||||
_LOGD ("client event %d", event);
|
||||
|
||||
@@ -658,10 +658,14 @@ dhcp_event_cb (sd_dhcp_client *client, int event, gpointer user_data)
|
||||
case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE:
|
||||
bound4_handle (self);
|
||||
break;
|
||||
case SD_DHCP_CLIENT_EVENT_SELECTING:
|
||||
break;
|
||||
default:
|
||||
_LOGW ("unhandled DHCP event %d", event);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@@ -5,7 +5,7 @@
|
||||
Copyright © 2014 Axis Communications AB. All rights reserved.
|
||||
***/
|
||||
|
||||
#include <netinet/if_ether.h>
|
||||
#include <net/ethernet.h>
|
||||
|
||||
#include "socket-util.h"
|
||||
#include "sparse-endian.h"
|
||||
|
@@ -616,7 +616,7 @@ int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t siz
|
||||
assert(data);
|
||||
|
||||
hex_buf = hexmem(data, size);
|
||||
if (hex_buf == NULL)
|
||||
if (!hex_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
fprintf(f, "%s=%s\n", key, hex_buf);
|
||||
|
@@ -89,7 +89,8 @@ struct sd_dhcp_client {
|
||||
uint32_t mtu;
|
||||
uint32_t xid;
|
||||
usec_t start_time;
|
||||
unsigned attempt;
|
||||
uint64_t attempt;
|
||||
uint64_t max_attempts;
|
||||
usec_t request_sent;
|
||||
sd_event_source *timeout_t1;
|
||||
sd_event_source *timeout_t2;
|
||||
@@ -524,10 +525,18 @@ int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp_client_set_max_attempts(sd_dhcp_client *client, uint64_t max_attempts) {
|
||||
assert_return(client, -EINVAL);
|
||||
|
||||
client->max_attempts = max_attempts;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
|
||||
assert_return(client, -EINVAL);
|
||||
|
||||
if (!IN_SET(client->state, DHCP_STATE_BOUND, DHCP_STATE_RENEWING, DHCP_STATE_REBINDING))
|
||||
if (!IN_SET(client->state, DHCP_STATE_SELECTING, DHCP_STATE_BOUND, DHCP_STATE_RENEWING, DHCP_STATE_REBINDING))
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
if (ret)
|
||||
@@ -536,11 +545,13 @@ int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void client_notify(sd_dhcp_client *client, int event) {
|
||||
static int client_notify(sd_dhcp_client *client, int event) {
|
||||
assert(client);
|
||||
|
||||
if (client->callback)
|
||||
client->callback(client, event, client->userdata);
|
||||
return client->callback(client, event, client->userdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int client_initialize(sd_dhcp_client *client) {
|
||||
@@ -555,7 +566,7 @@ static int client_initialize(sd_dhcp_client *client) {
|
||||
(void) event_source_disable(client->timeout_t2);
|
||||
(void) event_source_disable(client->timeout_expire);
|
||||
|
||||
client->attempt = 1;
|
||||
client->attempt = 0;
|
||||
|
||||
client->state = DHCP_STATE_INIT;
|
||||
client->xid = 0;
|
||||
@@ -599,7 +610,7 @@ static int client_message_init(
|
||||
assert(ret);
|
||||
assert(_optlen);
|
||||
assert(_optoffset);
|
||||
assert(IN_SET(type, DHCP_DISCOVER, DHCP_REQUEST));
|
||||
assert(IN_SET(type, DHCP_DISCOVER, DHCP_REQUEST, DHCP_RELEASE));
|
||||
|
||||
optlen = DHCP_MIN_OPTIONS_SIZE;
|
||||
size = sizeof(DHCPPacket) + optlen;
|
||||
@@ -690,7 +701,7 @@ static int client_message_init(
|
||||
MAY contain the Parameter Request List option. */
|
||||
/* NOTE: in case that there would be an option to do not send
|
||||
* any PRL at all, the size should be checked before sending */
|
||||
if (client->req_opts_size > 0) {
|
||||
if (client->req_opts_size > 0 && type != DHCP_RELEASE) {
|
||||
r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
|
||||
SD_DHCP_OPTION_PARAMETER_REQUEST_LIST,
|
||||
client->req_opts_size, client->req_opts);
|
||||
@@ -722,7 +733,7 @@ static int client_message_init(
|
||||
*/
|
||||
/* RFC7844 section 3:
|
||||
SHOULD NOT contain any other option. */
|
||||
if (!client->anonymize) {
|
||||
if (!client->anonymize && type != DHCP_RELEASE) {
|
||||
max_size = htobe16(size);
|
||||
r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
|
||||
SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
|
||||
@@ -854,6 +865,41 @@ static int client_send_discover(sd_dhcp_client *client) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int client_send_release(sd_dhcp_client *client) {
|
||||
_cleanup_free_ DHCPPacket *release = NULL;
|
||||
size_t optoffset, optlen;
|
||||
int r;
|
||||
|
||||
assert(client);
|
||||
assert(!IN_SET(client->state, DHCP_STATE_STOPPED));
|
||||
|
||||
r = client_message_init(client, &release, DHCP_RELEASE,
|
||||
&optlen, &optoffset);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Fill up release IP and MAC */
|
||||
release->dhcp.ciaddr = client->lease->address;
|
||||
memcpy(&release->dhcp.chaddr, &client->mac_addr, client->mac_addr_len);
|
||||
|
||||
r = dhcp_option_append(&release->dhcp, optlen, &optoffset, 0,
|
||||
SD_DHCP_OPTION_END, 0, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dhcp_network_send_udp_socket(client->fd,
|
||||
client->lease->server_address,
|
||||
DHCP_PORT_SERVER,
|
||||
&release->dhcp,
|
||||
sizeof(DHCPMessage) + optoffset);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
log_dhcp_client(client, "RELEASE");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int client_send_request(sd_dhcp_client *client) {
|
||||
_cleanup_free_ DHCPPacket *request = NULL;
|
||||
size_t optoffset, optlen;
|
||||
@@ -1054,10 +1100,12 @@ static int client_timeout_resend(
|
||||
case DHCP_STATE_REQUESTING:
|
||||
case DHCP_STATE_BOUND:
|
||||
|
||||
if (client->attempt < 64)
|
||||
client->attempt *= 2;
|
||||
if (client->attempt < client->max_attempts)
|
||||
client->attempt++;
|
||||
else
|
||||
goto error;
|
||||
|
||||
next_timeout = time_now + (client->attempt - 1) * USEC_PER_SEC;
|
||||
next_timeout = time_now + ((UINT64_C(1) << MIN(client->attempt, (uint64_t) 6)) - 1) * USEC_PER_SEC;
|
||||
|
||||
break;
|
||||
|
||||
@@ -1081,17 +1129,15 @@ static int client_timeout_resend(
|
||||
r = client_send_discover(client);
|
||||
if (r >= 0) {
|
||||
client->state = DHCP_STATE_SELECTING;
|
||||
client->attempt = 1;
|
||||
} else {
|
||||
if (client->attempt >= 64)
|
||||
goto error;
|
||||
}
|
||||
client->attempt = 0;
|
||||
} else if (client->attempt >= client->max_attempts)
|
||||
goto error;
|
||||
|
||||
break;
|
||||
|
||||
case DHCP_STATE_SELECTING:
|
||||
r = client_send_discover(client);
|
||||
if (r < 0 && client->attempt >= 64)
|
||||
if (r < 0 && client->attempt >= client->max_attempts)
|
||||
goto error;
|
||||
|
||||
break;
|
||||
@@ -1101,7 +1147,7 @@ static int client_timeout_resend(
|
||||
case DHCP_STATE_RENEWING:
|
||||
case DHCP_STATE_REBINDING:
|
||||
r = client_send_request(client);
|
||||
if (r < 0 && client->attempt >= 64)
|
||||
if (r < 0 && client->attempt >= client->max_attempts)
|
||||
goto error;
|
||||
|
||||
if (client->state == DHCP_STATE_INIT_REBOOT)
|
||||
@@ -1253,7 +1299,7 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata)
|
||||
client->fd = asynchronous_close(client->fd);
|
||||
|
||||
client->state = DHCP_STATE_REBINDING;
|
||||
client->attempt = 1;
|
||||
client->attempt = 0;
|
||||
|
||||
r = dhcp_network_bind_raw_socket(client->ifindex, &client->link,
|
||||
client->xid, client->mac_addr,
|
||||
@@ -1273,7 +1319,7 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata)
|
||||
DHCP_CLIENT_DONT_DESTROY(client);
|
||||
|
||||
client->state = DHCP_STATE_RENEWING;
|
||||
client->attempt = 1;
|
||||
client->attempt = 0;
|
||||
|
||||
return client_initialize_time_events(client);
|
||||
}
|
||||
@@ -1323,6 +1369,9 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_
|
||||
sd_dhcp_lease_unref(client->lease);
|
||||
client->lease = TAKE_PTR(lease);
|
||||
|
||||
if (client_notify(client, SD_DHCP_CLIENT_EVENT_SELECTING) < 0)
|
||||
return -ENOMSG;
|
||||
|
||||
log_dhcp_client(client, "OFFER");
|
||||
|
||||
return 0;
|
||||
@@ -1557,7 +1606,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i
|
||||
if (r >= 0) {
|
||||
|
||||
client->state = DHCP_STATE_REQUESTING;
|
||||
client->attempt = 1;
|
||||
client->attempt = 0;
|
||||
|
||||
r = event_reset_time(client->event, &client->timeout_resend,
|
||||
clock_boottime_or_monotonic(),
|
||||
@@ -1592,7 +1641,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i
|
||||
notify_event = r;
|
||||
|
||||
client->state = DHCP_STATE_BOUND;
|
||||
client->attempt = 1;
|
||||
client->attempt = 0;
|
||||
|
||||
client->last_addr = client->lease->address;
|
||||
|
||||
@@ -1848,6 +1897,14 @@ int sd_dhcp_client_start(sd_dhcp_client *client) {
|
||||
return r;
|
||||
}
|
||||
|
||||
int sd_dhcp_client_send_release(sd_dhcp_client *client) {
|
||||
assert_return(client, -EINVAL);
|
||||
|
||||
client_send_release(client);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp_client_stop(sd_dhcp_client *client) {
|
||||
DHCP_CLIENT_DONT_DESTROY(client);
|
||||
|
||||
@@ -1931,10 +1988,10 @@ int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) {
|
||||
.state = DHCP_STATE_INIT,
|
||||
.ifindex = -1,
|
||||
.fd = -1,
|
||||
.attempt = 1,
|
||||
.mtu = DHCP_DEFAULT_MIN_SIZE,
|
||||
.port = DHCP_PORT_CLIENT,
|
||||
.anonymize = !!anonymize,
|
||||
.max_attempts = (uint64_t) -1,
|
||||
};
|
||||
/* NOTE: this could be moved to a function. */
|
||||
if (anonymize) {
|
||||
|
@@ -7,7 +7,6 @@
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -833,7 +832,6 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
(void) fchmod(fileno(f), 0644);
|
||||
|
||||
fprintf(f,
|
||||
|
@@ -341,6 +341,12 @@ fail:
|
||||
|
||||
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_event, sd_event, event_free);
|
||||
|
||||
_public_ sd_event_source* sd_event_source_disable_unref(sd_event_source *s) {
|
||||
if (s)
|
||||
(void) sd_event_source_set_enabled(s, SD_EVENT_OFF);
|
||||
return sd_event_source_unref(s);
|
||||
}
|
||||
|
||||
static bool event_pid_changed(sd_event *e) {
|
||||
assert(e);
|
||||
|
||||
@@ -3026,7 +3032,7 @@ static void event_close_inode_data_fds(sd_event *e) {
|
||||
|
||||
/* Close the fds pointing to the inodes to watch now. We need to close them as they might otherwise pin
|
||||
* filesystems. But we can't close them right-away as we need them as long as the user still wants to make
|
||||
* adjustments to the even source, such as changing the priority (which requires us to remove and readd a watch
|
||||
* adjustments to the even source, such as changing the priority (which requires us to remove and re-add a watch
|
||||
* for the inode). Hence, let's close them when entering the first iteration after they were added, as a
|
||||
* compromise. */
|
||||
|
||||
|
@@ -41,7 +41,7 @@ int dns_label_unescape(const char **name, char *dest, size_t sz, DNSLabelFlags f
|
||||
d = dest;
|
||||
|
||||
for (;;) {
|
||||
if (*n == 0 || *n == '.') {
|
||||
if (IN_SET(*n, 0, '.')) {
|
||||
if (FLAGS_SET(flags, DNS_LABEL_LDH) && last_char == '-')
|
||||
/* Trailing dash */
|
||||
return -EINVAL;
|
||||
|
@@ -38,6 +38,7 @@ enum {
|
||||
SD_DHCP_CLIENT_EVENT_IP_CHANGE = 2,
|
||||
SD_DHCP_CLIENT_EVENT_EXPIRED = 3,
|
||||
SD_DHCP_CLIENT_EVENT_RENEW = 4,
|
||||
SD_DHCP_CLIENT_EVENT_SELECTING = 5,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -98,7 +99,7 @@ enum {
|
||||
|
||||
typedef struct sd_dhcp_client sd_dhcp_client;
|
||||
|
||||
typedef void (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, void *userdata);
|
||||
typedef int (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, void *userdata);
|
||||
int sd_dhcp_client_set_callback(
|
||||
sd_dhcp_client *client,
|
||||
sd_dhcp_client_callback_t cb,
|
||||
@@ -154,6 +155,9 @@ int sd_dhcp_client_get_client_id(
|
||||
int sd_dhcp_client_set_mtu(
|
||||
sd_dhcp_client *client,
|
||||
uint32_t mtu);
|
||||
int sd_dhcp_client_set_max_attempts(
|
||||
sd_dhcp_client *client,
|
||||
uint64_t attempt);
|
||||
int sd_dhcp_client_set_client_port(
|
||||
sd_dhcp_client *client,
|
||||
uint16_t port);
|
||||
@@ -172,6 +176,7 @@ int sd_dhcp_client_get_lease(
|
||||
|
||||
int sd_dhcp_client_stop(sd_dhcp_client *client);
|
||||
int sd_dhcp_client_start(sd_dhcp_client *client);
|
||||
int sd_dhcp_client_send_release(sd_dhcp_client *client);
|
||||
|
||||
sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client);
|
||||
sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client);
|
||||
|
@@ -113,6 +113,7 @@ int sd_event_get_iteration(sd_event *e, uint64_t *ret);
|
||||
|
||||
sd_event_source* sd_event_source_ref(sd_event_source *s);
|
||||
sd_event_source* sd_event_source_unref(sd_event_source *s);
|
||||
sd_event_source* sd_event_source_disable_unref(sd_event_source *s);
|
||||
|
||||
sd_event *sd_event_source_get_event(sd_event_source *s);
|
||||
void* sd_event_source_get_userdata(sd_event_source *s);
|
||||
@@ -149,6 +150,7 @@ int sd_event_source_set_floating(sd_event_source *s, int b);
|
||||
/* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */
|
||||
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref);
|
||||
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event_source, sd_event_source_unref);
|
||||
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event_source, sd_event_source_disable_unref);
|
||||
|
||||
_SD_END_DECLARATIONS;
|
||||
|
||||
|
Reference in New Issue
Block a user