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
|
static inline int
|
||||||
_nm_log_get_max_level_realm (void)
|
_nm_log_get_max_level_realm (void)
|
||||||
{
|
{
|
||||||
@@ -86,6 +97,14 @@ G_STMT_START { \
|
|||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <sys/ioctl.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
|
static inline pid_t
|
||||||
raw_getpid (void) {
|
raw_getpid (void) {
|
||||||
#if defined(__alpha__)
|
#if defined(__alpha__)
|
||||||
|
@@ -66,8 +66,31 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
|
|||||||
if (!q)
|
if (!q)
|
||||||
return NULL;
|
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;
|
*p = q;
|
||||||
*allocated = _unlikely_(size == 0) ? newalloc : malloc_usable_size(q) / size;
|
*allocated = newalloc;
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
#include "nm-sd-adapt-shared.h"
|
#include "nm-sd-adapt-shared.h"
|
||||||
|
|
||||||
#include <stdio_ext.h>
|
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "env-file.h"
|
#include "env-file.h"
|
||||||
#include "env-util.h"
|
#include "env-util.h"
|
||||||
@@ -548,7 +546,6 @@ int write_env_file(const char *fname, char **l) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
|
||||||
(void) fchmod_umask(fileno(f), 0644);
|
(void) fchmod_umask(fileno(f), 0644);
|
||||||
|
|
||||||
STRV_FOREACH(i, l)
|
STRV_FOREACH(i, l)
|
||||||
|
@@ -31,6 +31,52 @@
|
|||||||
|
|
||||||
#define READ_FULL_BYTES_MAX (4U*1024U*1024U)
|
#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 */
|
#if 0 /* NM_IGNORED */
|
||||||
int write_string_stream_ts(
|
int write_string_stream_ts(
|
||||||
FILE *f,
|
FILE *f,
|
||||||
@@ -98,7 +144,6 @@ static int write_string_file_atomic(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
|
||||||
(void) fchmod_umask(fileno(f), 0644);
|
(void) fchmod_umask(fileno(f), 0644);
|
||||||
|
|
||||||
r = write_string_stream_ts(f, line, flags, ts);
|
r = write_string_stream_ts(f, line, flags, ts);
|
||||||
@@ -144,11 +189,9 @@ int write_string_file_ts(
|
|||||||
assert(!ts);
|
assert(!ts);
|
||||||
|
|
||||||
if (flags & WRITE_STRING_FILE_CREATE) {
|
if (flags & WRITE_STRING_FILE_CREATE) {
|
||||||
f = fopen(fn, "we");
|
r = fopen_unlocked(fn, "we", &f);
|
||||||
if (!f) {
|
if (r < 0)
|
||||||
r = -errno;
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
@@ -160,16 +203,13 @@ int write_string_file_ts(
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
f = fdopen(fd, "w");
|
r = fdopen_unlocked(fd, "w", &f);
|
||||||
if (!f) {
|
if (r < 0) {
|
||||||
r = -errno;
|
|
||||||
safe_close(fd);
|
safe_close(fd);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
|
||||||
|
|
||||||
if (flags & WRITE_STRING_FILE_DISABLE_BUFFER)
|
if (flags & WRITE_STRING_FILE_DISABLE_BUFFER)
|
||||||
setvbuf(f, NULL, _IONBF, 0);
|
setvbuf(f, NULL, _IONBF, 0);
|
||||||
|
|
||||||
@@ -216,15 +256,14 @@ int write_string_filef(
|
|||||||
|
|
||||||
int read_one_line_file(const char *fn, char **line) {
|
int read_one_line_file(const char *fn, char **line) {
|
||||||
_cleanup_fclose_ FILE *f = NULL;
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
assert(fn);
|
assert(fn);
|
||||||
assert(line);
|
assert(line);
|
||||||
|
|
||||||
f = fopen(fn, "re");
|
r = fopen_unlocked(fn, "re", &f);
|
||||||
if (!f)
|
if (r < 0)
|
||||||
return -errno;
|
return r;
|
||||||
|
|
||||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
|
||||||
|
|
||||||
return read_line(f, LONG_LINE_MAX, line);
|
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_fclose_ FILE *f = NULL;
|
||||||
_cleanup_free_ char *buf = NULL;
|
_cleanup_free_ char *buf = NULL;
|
||||||
size_t l, k;
|
size_t l, k;
|
||||||
|
int r;
|
||||||
|
|
||||||
assert(fn);
|
assert(fn);
|
||||||
assert(blob);
|
assert(blob);
|
||||||
@@ -246,11 +286,9 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
|
|||||||
if (!buf)
|
if (!buf)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
f = fopen(fn, "re");
|
r = fopen_unlocked(fn, "re", &f);
|
||||||
if (!f)
|
if (r < 0)
|
||||||
return -errno;
|
return r;
|
||||||
|
|
||||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
|
||||||
|
|
||||||
/* We try to read one byte more than we need, so that we know whether we hit eof */
|
/* We try to read one byte more than we need, so that we know whether we hit eof */
|
||||||
errno = 0;
|
errno = 0;
|
||||||
@@ -283,7 +321,8 @@ int read_full_stream_full(
|
|||||||
|
|
||||||
assert(f);
|
assert(f);
|
||||||
assert(ret_contents);
|
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 */
|
n_next = LINE_MAX; /* Start size */
|
||||||
|
|
||||||
@@ -324,6 +363,7 @@ int read_full_stream_full(
|
|||||||
}
|
}
|
||||||
memcpy_safe(t, buf, n);
|
memcpy_safe(t, buf, n);
|
||||||
explicit_bzero_safe(buf, n);
|
explicit_bzero_safe(buf, n);
|
||||||
|
buf = mfree(buf);
|
||||||
} else {
|
} else {
|
||||||
t = realloc(buf, n_next + 1);
|
t = realloc(buf, n_next + 1);
|
||||||
if (!t)
|
if (!t)
|
||||||
@@ -360,9 +400,12 @@ int read_full_stream_full(
|
|||||||
n_next = MIN(n * 2, READ_FULL_BYTES_MAX);
|
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;
|
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;
|
goto finalize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,15 +437,14 @@ finalize:
|
|||||||
|
|
||||||
int read_full_file_full(const char *filename, ReadFullFileFlags flags, char **contents, size_t *size) {
|
int read_full_file_full(const char *filename, ReadFullFileFlags flags, char **contents, size_t *size) {
|
||||||
_cleanup_fclose_ FILE *f = NULL;
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
assert(filename);
|
assert(filename);
|
||||||
assert(contents);
|
assert(contents);
|
||||||
|
|
||||||
f = fopen(filename, "re");
|
r = fopen_unlocked(filename, "re", &f);
|
||||||
if (!f)
|
if (r < 0)
|
||||||
return -errno;
|
return r;
|
||||||
|
|
||||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
|
||||||
|
|
||||||
return read_full_stream_full(f, filename, flags, contents, size);
|
return read_full_stream_full(f, filename, flags, contents, size);
|
||||||
}
|
}
|
||||||
|
@@ -31,8 +31,14 @@ typedef enum {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
READ_FULL_FILE_SECURE = 1 << 0,
|
READ_FULL_FILE_SECURE = 1 << 0,
|
||||||
READ_FULL_FILE_UNBASE64 = 1 << 1,
|
READ_FULL_FILE_UNBASE64 = 1 << 1,
|
||||||
|
READ_FULL_FILE_UNHEX = 1 << 2,
|
||||||
} ReadFullFileFlags;
|
} 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);
|
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) {
|
static inline int write_string_stream(FILE *f, const char *line, WriteStringFileFlags flags) {
|
||||||
return write_string_stream_ts(f, line, flags, NULL);
|
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;
|
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;
|
_cleanup_free_ uint8_t *buf = NULL;
|
||||||
|
size_t buf_size;
|
||||||
const char *x;
|
const char *x;
|
||||||
uint8_t *z;
|
uint8_t *z;
|
||||||
|
int r;
|
||||||
|
|
||||||
assert(ret);
|
assert(ret);
|
||||||
assert(ret_len);
|
assert(ret_len);
|
||||||
@@ -123,7 +125,8 @@ int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) {
|
|||||||
l = strlen(p);
|
l = strlen(p);
|
||||||
|
|
||||||
/* Note that the calculation of memory size is an upper boundary, as we ignore whitespace while decoding */
|
/* 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)
|
if (!buf)
|
||||||
return -ENOMEM;
|
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);
|
a = unhex_next(&x, &l);
|
||||||
if (a == -EPIPE) /* End of string */
|
if (a == -EPIPE) /* End of string */
|
||||||
break;
|
break;
|
||||||
if (a < 0)
|
if (a < 0) {
|
||||||
return a;
|
r = a;
|
||||||
|
goto on_failure;
|
||||||
|
}
|
||||||
|
|
||||||
b = unhex_next(&x, &l);
|
b = unhex_next(&x, &l);
|
||||||
if (b < 0)
|
if (b < 0) {
|
||||||
return b;
|
r = b;
|
||||||
|
goto on_failure;
|
||||||
|
}
|
||||||
|
|
||||||
*(z++) = (uint8_t) a << 4 | (uint8_t) b;
|
*(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);
|
*ret = TAKE_PTR(buf);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
on_failure:
|
||||||
|
if (secure)
|
||||||
|
explicit_bzero_safe(buf, buf_size);
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 /* NM_IGNORED */
|
#if 0 /* NM_IGNORED */
|
||||||
|
@@ -18,7 +18,10 @@ char hexchar(int x) _const_;
|
|||||||
int unhexchar(char c) _const_;
|
int unhexchar(char c) _const_;
|
||||||
|
|
||||||
char *hexmem(const void *p, size_t l);
|
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_;
|
char base32hexchar(int x) _const_;
|
||||||
int unbase32hexchar(char c) _const_;
|
int unbase32hexchar(char c) _const_;
|
||||||
|
@@ -106,6 +106,15 @@
|
|||||||
_Pragma("GCC diagnostic push"); \
|
_Pragma("GCC diagnostic push"); \
|
||||||
_Pragma("GCC diagnostic ignored \"-Wincompatible-pointer-types\"")
|
_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 \
|
#define REENABLE_WARNING \
|
||||||
_Pragma("GCC diagnostic pop")
|
_Pragma("GCC diagnostic pop")
|
||||||
#else
|
#else
|
||||||
|
@@ -10,7 +10,6 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdio_ext.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/mman.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;
|
char *k;
|
||||||
_cleanup_free_ char *ans = NULL;
|
_cleanup_free_ char *ans = NULL;
|
||||||
const char *p;
|
const char *p;
|
||||||
int c;
|
int c, r;
|
||||||
|
|
||||||
assert(line);
|
assert(line);
|
||||||
assert(pid >= 0);
|
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. */
|
* comm_fallback is false). Returns 0 and sets *line otherwise. */
|
||||||
|
|
||||||
p = procfs_file_alloca(pid, "cmdline");
|
p = procfs_file_alloca(pid, "cmdline");
|
||||||
|
r = fopen_unlocked(p, "re", &f);
|
||||||
f = fopen(p, "re");
|
if (r == -ENOENT)
|
||||||
if (!f) {
|
return -ESRCH;
|
||||||
if (errno == ENOENT)
|
if (r < 0)
|
||||||
return -ESRCH;
|
return r;
|
||||||
return -errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
|
||||||
|
|
||||||
if (max_length == 0) {
|
if (max_length == 0) {
|
||||||
/* This is supposed to be a safety guard against runaway command lines. */
|
/* 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;
|
return -EINVAL;
|
||||||
|
|
||||||
p = procfs_file_alloca(pid, "status");
|
p = procfs_file_alloca(pid, "status");
|
||||||
f = fopen(p, "re");
|
r = fopen_unlocked(p, "re", &f);
|
||||||
if (!f) {
|
if (r == -ENOENT)
|
||||||
if (errno == ENOENT)
|
return -ESRCH;
|
||||||
return -ESRCH;
|
if (r < 0)
|
||||||
return -errno;
|
return r;
|
||||||
}
|
|
||||||
|
|
||||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
_cleanup_free_ char *line = NULL;
|
_cleanup_free_ char *line = NULL;
|
||||||
@@ -607,14 +599,11 @@ int get_process_environ(pid_t pid, char **env) {
|
|||||||
|
|
||||||
p = procfs_file_alloca(pid, "environ");
|
p = procfs_file_alloca(pid, "environ");
|
||||||
|
|
||||||
f = fopen(p, "re");
|
r = fopen_unlocked(p, "re", &f);
|
||||||
if (!f) {
|
if (r == -ENOENT)
|
||||||
if (errno == ENOENT)
|
return -ESRCH;
|
||||||
return -ESRCH;
|
if (r < 0)
|
||||||
return -errno;
|
return r;
|
||||||
}
|
|
||||||
|
|
||||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char c;
|
char c;
|
||||||
@@ -900,15 +889,11 @@ int getenv_for_pid(pid_t pid, const char *field, char **ret) {
|
|||||||
|
|
||||||
path = procfs_file_alloca(pid, "environ");
|
path = procfs_file_alloca(pid, "environ");
|
||||||
|
|
||||||
f = fopen(path, "re");
|
r = fopen_unlocked(path, "re", &f);
|
||||||
if (!f) {
|
if (r == -ENOENT)
|
||||||
if (errno == ENOENT)
|
return -ESRCH;
|
||||||
return -ESRCH;
|
if (r < 0)
|
||||||
|
return r;
|
||||||
return -errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
|
||||||
|
|
||||||
l = strlen(field);
|
l = strlen(field);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@@ -30,13 +30,15 @@
|
|||||||
#include "io-util.h"
|
#include "io-util.h"
|
||||||
#include "missing.h"
|
#include "missing.h"
|
||||||
#include "random-util.h"
|
#include "random-util.h"
|
||||||
|
#include "siphash24.h"
|
||||||
#include "time-util.h"
|
#include "time-util.h"
|
||||||
|
|
||||||
int rdrand(unsigned long *ret) {
|
int rdrand(unsigned long *ret) {
|
||||||
|
|
||||||
#if defined(__i386__) || defined(__x86_64__)
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
static int have_rdrand = -1;
|
static int have_rdrand = -1;
|
||||||
unsigned char err;
|
unsigned long v;
|
||||||
|
uint8_t success;
|
||||||
|
|
||||||
if (have_rdrand < 0) {
|
if (have_rdrand < 0) {
|
||||||
uint32_t eax, ebx, ecx, edx;
|
uint32_t eax, ebx, ecx, edx;
|
||||||
@@ -47,7 +49,12 @@ int rdrand(unsigned long *ret) {
|
|||||||
return -EOPNOTSUPP;
|
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)
|
if (have_rdrand == 0)
|
||||||
@@ -55,12 +62,24 @@ int rdrand(unsigned long *ret) {
|
|||||||
|
|
||||||
asm volatile("rdrand %0;"
|
asm volatile("rdrand %0;"
|
||||||
"setc %1"
|
"setc %1"
|
||||||
: "=r" (*ret),
|
: "=r" (v),
|
||||||
"=qm" (err));
|
"=qm" (success));
|
||||||
msan_unpoison(&err, sizeof(err));
|
msan_unpoison(&success, sizeof(success));
|
||||||
if (!err)
|
if (!success)
|
||||||
return -EAGAIN;
|
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;
|
return 0;
|
||||||
#else
|
#else
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
@@ -73,21 +92,22 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
|
|||||||
bool got_some = false;
|
bool got_some = false;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* Gathers some randomness from the kernel (or the CPU if the RANDOM_ALLOW_RDRAND flag is set). This call won't
|
/* Gathers some randomness from the kernel (or the CPU if the RANDOM_ALLOW_RDRAND flag is set). This
|
||||||
* block, unless the RANDOM_BLOCK flag is set. If RANDOM_DONT_DRAIN is set, an error is returned if the random
|
* call won't block, unless the RANDOM_BLOCK flag is set. If RANDOM_MAY_FAIL is set, an error is
|
||||||
* pool is not initialized. Otherwise it will always return some data from the kernel, regardless of whether
|
* returned if the random pool is not initialized. Otherwise it will always return some data from the
|
||||||
* the random pool is fully initialized or not. */
|
* kernel, regardless of whether the random pool is fully initialized or not. */
|
||||||
|
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (FLAGS_SET(flags, RANDOM_ALLOW_RDRAND))
|
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
|
/* Try x86-64' RDRAND intrinsic if we have it. We only use it if high quality randomness is
|
||||||
* required, as we don't trust it (who does?). Note that we only do a single iteration of RDRAND here,
|
* not required, as we don't trust it (who does?). Note that we only do a single iteration of
|
||||||
* even though the Intel docs suggest calling this in a tight loop of 10 invocations or so. That's
|
* RDRAND here, even though the Intel docs suggest calling this in a tight loop of 10
|
||||||
* because we don't really care about the quality here. We generally prefer using RDRAND if the caller
|
* invocations or so. That's because we don't really care about the quality here. We
|
||||||
* allows us too, since this way we won't drain the kernel randomness pool if we don't need it, as the
|
* generally prefer using RDRAND if the caller allows us to, since this way we won't upset
|
||||||
* pool's entropy is scarce. */
|
* 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 (;;) {
|
for (;;) {
|
||||||
unsigned long u;
|
unsigned long u;
|
||||||
size_t m;
|
size_t m;
|
||||||
@@ -162,12 +182,13 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
} else if (errno == EAGAIN) {
|
} else if (errno == EAGAIN) {
|
||||||
/* The kernel has no entropy whatsoever. Let's remember to use the syscall the next
|
/* The kernel has no entropy whatsoever. Let's remember to use the syscall
|
||||||
* time again though.
|
* the next time again though.
|
||||||
*
|
*
|
||||||
* If RANDOM_DONT_DRAIN is set, return an error so that random_bytes() can produce some
|
* If RANDOM_MAY_FAIL is set, return an error so that random_bytes() can
|
||||||
* pseudo-random bytes instead. Otherwise, fall back to /dev/urandom, which we know is empty,
|
* produce some pseudo-random bytes instead. Otherwise, fall back to
|
||||||
* but the kernel will produce some bytes for us on a best-effort basis. */
|
* /dev/urandom, which we know is empty, but the kernel will produce some
|
||||||
|
* bytes for us on a best-effort basis. */
|
||||||
have_syscall = true;
|
have_syscall = true;
|
||||||
|
|
||||||
if (got_some && FLAGS_SET(flags, RANDOM_EXTEND_WITH_PSEUDO)) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FLAGS_SET(flags, RANDOM_DONT_DRAIN))
|
if (FLAGS_SET(flags, RANDOM_MAY_FAIL))
|
||||||
return -ENODATA;
|
return -ENODATA;
|
||||||
|
|
||||||
/* Use /dev/urandom instead */
|
/* Use /dev/urandom instead */
|
||||||
@@ -205,14 +226,19 @@ void initialize_srand(void) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
#if HAVE_SYS_AUXV_H
|
#if HAVE_SYS_AUXV_H
|
||||||
/* The kernel provides us with 16 bytes of entropy in auxv, so let's
|
/* The kernel provides us with 16 bytes of entropy in auxv, so let's try to make use of that to seed
|
||||||
* try to make use of that to seed the pseudo-random generator. It's
|
* the pseudo-random generator. It's better than nothing... But let's first hash it to make it harder
|
||||||
* better than nothing... */
|
* 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) {
|
if (auxv) {
|
||||||
assert_cc(sizeof(x) <= 16);
|
static const uint8_t auxval_hash_key[16] = {
|
||||||
memcpy(&x, auxv, sizeof(x));
|
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
|
} else
|
||||||
#endif
|
#endif
|
||||||
x = 0;
|
x = 0;
|
||||||
@@ -259,7 +285,7 @@ void pseudo_random_bytes(void *p, size_t n) {
|
|||||||
|
|
||||||
void 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;
|
return;
|
||||||
|
|
||||||
/* If for some reason some user made /dev/urandom unavailable to us, or the kernel has no entropy, use a PRNG instead. */
|
/* 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 {
|
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_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_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 */
|
RANDOM_ALLOW_RDRAND = 1 << 3, /* Allow usage of the CPU RNG */
|
||||||
} RandomFlags;
|
} 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 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. */
|
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 */
|
#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) {
|
int flush_accept(int fd) {
|
||||||
|
|
||||||
struct pollfd pollfd = {
|
struct pollfd pollfd = {
|
||||||
.fd = fd,
|
.fd = fd,
|
||||||
.events = POLLIN,
|
.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;
|
int cfd;
|
||||||
|
|
||||||
r = poll(&pollfd, 1, 0);
|
r = poll(&pollfd, 1, 0);
|
||||||
@@ -1247,6 +1264,10 @@ int flush_accept(int fd) {
|
|||||||
if (r == 0)
|
if (r == 0)
|
||||||
return 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);
|
cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
|
||||||
if (cfd < 0) {
|
if (cfd < 0) {
|
||||||
if (errno == EAGAIN)
|
if (errno == EAGAIN)
|
||||||
|
@@ -6,7 +6,6 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdio_ext.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -736,6 +735,7 @@ char *strreplace(const char *text, const char *old_string, const char *new_strin
|
|||||||
return ret;
|
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) {
|
static void advance_offsets(ssize_t diff, size_t offsets[static 2], size_t shift[static 2], size_t size) {
|
||||||
if (!offsets)
|
if (!offsets)
|
||||||
return;
|
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
|
* 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
|
* 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
|
* Everything else will be left as it is. In particular other ANSI sequences are left as they are, as
|
||||||
* other special characters. Truncated ANSI sequences are left-as is too. This call is supposed to suppress the
|
* are any other special characters. Truncated ANSI sequences are left-as is too. This call is
|
||||||
* most basic formatting noise, but nothing else.
|
* 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. */
|
* Why care for CSO sequences? Well, to undo what terminal_urlify() and friends generate. */
|
||||||
|
|
||||||
isz = _isz ? *_isz : strlen(*ibuf);
|
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)
|
if (!f)
|
||||||
return NULL;
|
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++) {
|
for (i = *ibuf; i < *ibuf + isz + 1; i++) {
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@@ -872,7 +869,6 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
|
|||||||
return obuf;
|
return obuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 /* NM_IGNORED */
|
|
||||||
char *strextend_with_separator(char **x, const char *separator, ...) {
|
char *strextend_with_separator(char **x, const char *separator, ...) {
|
||||||
bool need_separator;
|
bool need_separator;
|
||||||
size_t f, l, l_separator;
|
size_t f, l, l_separator;
|
||||||
|
@@ -212,6 +212,12 @@ static inline size_t strlen_ptr(const char *s) {
|
|||||||
return strlen(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 */
|
/* Like startswith(), but operates on arbitrary memory blocks */
|
||||||
static inline void *memory_startswith(const void *p, size_t sz, const char *token) {
|
static inline void *memory_startswith(const void *p, size_t sz, const char *token) {
|
||||||
size_t n;
|
size_t n;
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
|
#include "fileio.h"
|
||||||
#include "fs-util.h"
|
#include "fs-util.h"
|
||||||
#include "hexdecoct.h"
|
#include "hexdecoct.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
@@ -39,12 +40,15 @@ int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
|
|||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
f = fdopen(fd, "w");
|
/* This assumes that returned FILE object is short-lived and used within the same single-threaded
|
||||||
if (!f) {
|
* context and never shared externally, hence locking is not necessary. */
|
||||||
unlink_noerrno(t);
|
|
||||||
|
r = fdopen_unlocked(fd, "w", &f);
|
||||||
|
if (r < 0) {
|
||||||
|
unlink(t);
|
||||||
free(t);
|
free(t);
|
||||||
safe_close(fd);
|
safe_close(fd);
|
||||||
return -errno;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
*_f = f;
|
*_f = f;
|
||||||
|
@@ -8,21 +8,19 @@
|
|||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
|
|
||||||
static inline void umaskp(mode_t *u) {
|
static inline void umaskp(mode_t *u) {
|
||||||
umask(*u);
|
umask(*u & 0777);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define _cleanup_umask_ _cleanup_(umaskp)
|
#define _cleanup_umask_ _cleanup_(umaskp)
|
||||||
|
|
||||||
struct _umask_struct_ {
|
/* We make use of the fact here that the umask() concept is using only the lower 9 bits of mode_t, although
|
||||||
mode_t mask;
|
* mode_t has space for the file type in the bits further up. We simply OR in the file type mask S_IFMT to
|
||||||
bool quit;
|
* 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) {
|
assert_cc((S_IFMT & 0777) == 0);
|
||||||
umask(s->mask);
|
|
||||||
};
|
|
||||||
|
|
||||||
#define RUN_WITH_UMASK(mask) \
|
#define RUN_WITH_UMASK(mask) \
|
||||||
for (_cleanup_(_reset_umask_) struct _umask_struct_ _saved_umask_ = { umask(mask), false }; \
|
for (_cleanup_umask_ mode_t _saved_umask_ = umask(mask) | S_IFMT; \
|
||||||
!_saved_umask_.quit ; \
|
FLAGS_SET(_saved_umask_, S_IFMT); \
|
||||||
_saved_umask_.quit = true)
|
_saved_umask_ &= 0777)
|
||||||
|
@@ -636,13 +636,13 @@ bound4_handle (NMDhcpSystemd *self)
|
|||||||
options);
|
options);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
dhcp_event_cb (sd_dhcp_client *client, int event, gpointer user_data)
|
dhcp_event_cb (sd_dhcp_client *client, int event, gpointer user_data)
|
||||||
{
|
{
|
||||||
NMDhcpSystemd *self = NM_DHCP_SYSTEMD (user_data);
|
NMDhcpSystemd *self = NM_DHCP_SYSTEMD (user_data);
|
||||||
NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (self);
|
NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (self);
|
||||||
|
|
||||||
g_assert (priv->client4 == client);
|
nm_assert (priv->client4 == client);
|
||||||
|
|
||||||
_LOGD ("client event %d", event);
|
_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:
|
case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE:
|
||||||
bound4_handle (self);
|
bound4_handle (self);
|
||||||
break;
|
break;
|
||||||
|
case SD_DHCP_CLIENT_EVENT_SELECTING:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
_LOGW ("unhandled DHCP event %d", event);
|
_LOGW ("unhandled DHCP event %d", event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
Copyright © 2014 Axis Communications AB. All rights reserved.
|
Copyright © 2014 Axis Communications AB. All rights reserved.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#include <netinet/if_ether.h>
|
#include <net/ethernet.h>
|
||||||
|
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
#include "sparse-endian.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);
|
assert(data);
|
||||||
|
|
||||||
hex_buf = hexmem(data, size);
|
hex_buf = hexmem(data, size);
|
||||||
if (hex_buf == NULL)
|
if (!hex_buf)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
fprintf(f, "%s=%s\n", key, hex_buf);
|
fprintf(f, "%s=%s\n", key, hex_buf);
|
||||||
|
@@ -89,7 +89,8 @@ struct sd_dhcp_client {
|
|||||||
uint32_t mtu;
|
uint32_t mtu;
|
||||||
uint32_t xid;
|
uint32_t xid;
|
||||||
usec_t start_time;
|
usec_t start_time;
|
||||||
unsigned attempt;
|
uint64_t attempt;
|
||||||
|
uint64_t max_attempts;
|
||||||
usec_t request_sent;
|
usec_t request_sent;
|
||||||
sd_event_source *timeout_t1;
|
sd_event_source *timeout_t1;
|
||||||
sd_event_source *timeout_t2;
|
sd_event_source *timeout_t2;
|
||||||
@@ -524,10 +525,18 @@ int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) {
|
|||||||
return 0;
|
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) {
|
int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
|
||||||
assert_return(client, -EINVAL);
|
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;
|
return -EADDRNOTAVAIL;
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
@@ -536,11 +545,13 @@ int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void client_notify(sd_dhcp_client *client, int event) {
|
static int client_notify(sd_dhcp_client *client, int event) {
|
||||||
assert(client);
|
assert(client);
|
||||||
|
|
||||||
if (client->callback)
|
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) {
|
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_t2);
|
||||||
(void) event_source_disable(client->timeout_expire);
|
(void) event_source_disable(client->timeout_expire);
|
||||||
|
|
||||||
client->attempt = 1;
|
client->attempt = 0;
|
||||||
|
|
||||||
client->state = DHCP_STATE_INIT;
|
client->state = DHCP_STATE_INIT;
|
||||||
client->xid = 0;
|
client->xid = 0;
|
||||||
@@ -599,7 +610,7 @@ static int client_message_init(
|
|||||||
assert(ret);
|
assert(ret);
|
||||||
assert(_optlen);
|
assert(_optlen);
|
||||||
assert(_optoffset);
|
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;
|
optlen = DHCP_MIN_OPTIONS_SIZE;
|
||||||
size = sizeof(DHCPPacket) + optlen;
|
size = sizeof(DHCPPacket) + optlen;
|
||||||
@@ -690,7 +701,7 @@ static int client_message_init(
|
|||||||
MAY contain the Parameter Request List option. */
|
MAY contain the Parameter Request List option. */
|
||||||
/* NOTE: in case that there would be an option to do not send
|
/* NOTE: in case that there would be an option to do not send
|
||||||
* any PRL at all, the size should be checked before sending */
|
* 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,
|
r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
|
||||||
SD_DHCP_OPTION_PARAMETER_REQUEST_LIST,
|
SD_DHCP_OPTION_PARAMETER_REQUEST_LIST,
|
||||||
client->req_opts_size, client->req_opts);
|
client->req_opts_size, client->req_opts);
|
||||||
@@ -722,7 +733,7 @@ static int client_message_init(
|
|||||||
*/
|
*/
|
||||||
/* RFC7844 section 3:
|
/* RFC7844 section 3:
|
||||||
SHOULD NOT contain any other option. */
|
SHOULD NOT contain any other option. */
|
||||||
if (!client->anonymize) {
|
if (!client->anonymize && type != DHCP_RELEASE) {
|
||||||
max_size = htobe16(size);
|
max_size = htobe16(size);
|
||||||
r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
|
r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
|
||||||
SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
|
SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
|
||||||
@@ -854,6 +865,41 @@ static int client_send_discover(sd_dhcp_client *client) {
|
|||||||
return 0;
|
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) {
|
static int client_send_request(sd_dhcp_client *client) {
|
||||||
_cleanup_free_ DHCPPacket *request = NULL;
|
_cleanup_free_ DHCPPacket *request = NULL;
|
||||||
size_t optoffset, optlen;
|
size_t optoffset, optlen;
|
||||||
@@ -1054,10 +1100,12 @@ static int client_timeout_resend(
|
|||||||
case DHCP_STATE_REQUESTING:
|
case DHCP_STATE_REQUESTING:
|
||||||
case DHCP_STATE_BOUND:
|
case DHCP_STATE_BOUND:
|
||||||
|
|
||||||
if (client->attempt < 64)
|
if (client->attempt < client->max_attempts)
|
||||||
client->attempt *= 2;
|
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;
|
break;
|
||||||
|
|
||||||
@@ -1081,17 +1129,15 @@ static int client_timeout_resend(
|
|||||||
r = client_send_discover(client);
|
r = client_send_discover(client);
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
client->state = DHCP_STATE_SELECTING;
|
client->state = DHCP_STATE_SELECTING;
|
||||||
client->attempt = 1;
|
client->attempt = 0;
|
||||||
} else {
|
} else if (client->attempt >= client->max_attempts)
|
||||||
if (client->attempt >= 64)
|
goto error;
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DHCP_STATE_SELECTING:
|
case DHCP_STATE_SELECTING:
|
||||||
r = client_send_discover(client);
|
r = client_send_discover(client);
|
||||||
if (r < 0 && client->attempt >= 64)
|
if (r < 0 && client->attempt >= client->max_attempts)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -1101,7 +1147,7 @@ static int client_timeout_resend(
|
|||||||
case DHCP_STATE_RENEWING:
|
case DHCP_STATE_RENEWING:
|
||||||
case DHCP_STATE_REBINDING:
|
case DHCP_STATE_REBINDING:
|
||||||
r = client_send_request(client);
|
r = client_send_request(client);
|
||||||
if (r < 0 && client->attempt >= 64)
|
if (r < 0 && client->attempt >= client->max_attempts)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (client->state == DHCP_STATE_INIT_REBOOT)
|
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->fd = asynchronous_close(client->fd);
|
||||||
|
|
||||||
client->state = DHCP_STATE_REBINDING;
|
client->state = DHCP_STATE_REBINDING;
|
||||||
client->attempt = 1;
|
client->attempt = 0;
|
||||||
|
|
||||||
r = dhcp_network_bind_raw_socket(client->ifindex, &client->link,
|
r = dhcp_network_bind_raw_socket(client->ifindex, &client->link,
|
||||||
client->xid, client->mac_addr,
|
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);
|
DHCP_CLIENT_DONT_DESTROY(client);
|
||||||
|
|
||||||
client->state = DHCP_STATE_RENEWING;
|
client->state = DHCP_STATE_RENEWING;
|
||||||
client->attempt = 1;
|
client->attempt = 0;
|
||||||
|
|
||||||
return client_initialize_time_events(client);
|
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);
|
sd_dhcp_lease_unref(client->lease);
|
||||||
client->lease = TAKE_PTR(lease);
|
client->lease = TAKE_PTR(lease);
|
||||||
|
|
||||||
|
if (client_notify(client, SD_DHCP_CLIENT_EVENT_SELECTING) < 0)
|
||||||
|
return -ENOMSG;
|
||||||
|
|
||||||
log_dhcp_client(client, "OFFER");
|
log_dhcp_client(client, "OFFER");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1557,7 +1606,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i
|
|||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
|
|
||||||
client->state = DHCP_STATE_REQUESTING;
|
client->state = DHCP_STATE_REQUESTING;
|
||||||
client->attempt = 1;
|
client->attempt = 0;
|
||||||
|
|
||||||
r = event_reset_time(client->event, &client->timeout_resend,
|
r = event_reset_time(client->event, &client->timeout_resend,
|
||||||
clock_boottime_or_monotonic(),
|
clock_boottime_or_monotonic(),
|
||||||
@@ -1592,7 +1641,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i
|
|||||||
notify_event = r;
|
notify_event = r;
|
||||||
|
|
||||||
client->state = DHCP_STATE_BOUND;
|
client->state = DHCP_STATE_BOUND;
|
||||||
client->attempt = 1;
|
client->attempt = 0;
|
||||||
|
|
||||||
client->last_addr = client->lease->address;
|
client->last_addr = client->lease->address;
|
||||||
|
|
||||||
@@ -1848,6 +1897,14 @@ int sd_dhcp_client_start(sd_dhcp_client *client) {
|
|||||||
return r;
|
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) {
|
int sd_dhcp_client_stop(sd_dhcp_client *client) {
|
||||||
DHCP_CLIENT_DONT_DESTROY(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,
|
.state = DHCP_STATE_INIT,
|
||||||
.ifindex = -1,
|
.ifindex = -1,
|
||||||
.fd = -1,
|
.fd = -1,
|
||||||
.attempt = 1,
|
|
||||||
.mtu = DHCP_DEFAULT_MIN_SIZE,
|
.mtu = DHCP_DEFAULT_MIN_SIZE,
|
||||||
.port = DHCP_PORT_CLIENT,
|
.port = DHCP_PORT_CLIENT,
|
||||||
.anonymize = !!anonymize,
|
.anonymize = !!anonymize,
|
||||||
|
.max_attempts = (uint64_t) -1,
|
||||||
};
|
};
|
||||||
/* NOTE: this could be moved to a function. */
|
/* NOTE: this could be moved to a function. */
|
||||||
if (anonymize) {
|
if (anonymize) {
|
||||||
|
@@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdio_ext.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@@ -833,7 +832,6 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
|
||||||
(void) fchmod(fileno(f), 0644);
|
(void) fchmod(fileno(f), 0644);
|
||||||
|
|
||||||
fprintf(f,
|
fprintf(f,
|
||||||
|
@@ -341,6 +341,12 @@ fail:
|
|||||||
|
|
||||||
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_event, sd_event, event_free);
|
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) {
|
static bool event_pid_changed(sd_event *e) {
|
||||||
assert(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
|
/* 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
|
* 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
|
* for the inode). Hence, let's close them when entering the first iteration after they were added, as a
|
||||||
* compromise. */
|
* compromise. */
|
||||||
|
|
||||||
|
@@ -41,7 +41,7 @@ int dns_label_unescape(const char **name, char *dest, size_t sz, DNSLabelFlags f
|
|||||||
d = dest;
|
d = dest;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (*n == 0 || *n == '.') {
|
if (IN_SET(*n, 0, '.')) {
|
||||||
if (FLAGS_SET(flags, DNS_LABEL_LDH) && last_char == '-')
|
if (FLAGS_SET(flags, DNS_LABEL_LDH) && last_char == '-')
|
||||||
/* Trailing dash */
|
/* Trailing dash */
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@@ -38,6 +38,7 @@ enum {
|
|||||||
SD_DHCP_CLIENT_EVENT_IP_CHANGE = 2,
|
SD_DHCP_CLIENT_EVENT_IP_CHANGE = 2,
|
||||||
SD_DHCP_CLIENT_EVENT_EXPIRED = 3,
|
SD_DHCP_CLIENT_EVENT_EXPIRED = 3,
|
||||||
SD_DHCP_CLIENT_EVENT_RENEW = 4,
|
SD_DHCP_CLIENT_EVENT_RENEW = 4,
|
||||||
|
SD_DHCP_CLIENT_EVENT_SELECTING = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -98,7 +99,7 @@ enum {
|
|||||||
|
|
||||||
typedef struct sd_dhcp_client sd_dhcp_client;
|
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(
|
int sd_dhcp_client_set_callback(
|
||||||
sd_dhcp_client *client,
|
sd_dhcp_client *client,
|
||||||
sd_dhcp_client_callback_t cb,
|
sd_dhcp_client_callback_t cb,
|
||||||
@@ -154,6 +155,9 @@ int sd_dhcp_client_get_client_id(
|
|||||||
int sd_dhcp_client_set_mtu(
|
int sd_dhcp_client_set_mtu(
|
||||||
sd_dhcp_client *client,
|
sd_dhcp_client *client,
|
||||||
uint32_t mtu);
|
uint32_t mtu);
|
||||||
|
int sd_dhcp_client_set_max_attempts(
|
||||||
|
sd_dhcp_client *client,
|
||||||
|
uint64_t attempt);
|
||||||
int sd_dhcp_client_set_client_port(
|
int sd_dhcp_client_set_client_port(
|
||||||
sd_dhcp_client *client,
|
sd_dhcp_client *client,
|
||||||
uint16_t port);
|
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_stop(sd_dhcp_client *client);
|
||||||
int sd_dhcp_client_start(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_ref(sd_dhcp_client *client);
|
||||||
sd_dhcp_client *sd_dhcp_client_unref(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_ref(sd_event_source *s);
|
||||||
sd_event_source* sd_event_source_unref(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);
|
sd_event *sd_event_source_get_event(sd_event_source *s);
|
||||||
void* sd_event_source_get_userdata(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. */
|
/* 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, 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_unref);
|
||||||
|
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event_source, sd_event_source_disable_unref);
|
||||||
|
|
||||||
_SD_END_DECLARATIONS;
|
_SD_END_DECLARATIONS;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user