systemd: merge branch systemd into master

This commit is contained in:
Thomas Haller
2019-09-25 09:10:44 +02:00
21 changed files with 265 additions and 63 deletions

View File

@@ -80,7 +80,7 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
* take possession of the extra space. This should be cheap, since libc doesn't have to move * take possession of the extra space. This should be cheap, since libc doesn't have to move
* the memory for this. */ * the memory for this. */
qq = realloc(q, bn * size); qq = reallocarray(q, bn, size);
if (_likely_(qq)) { if (_likely_(qq)) {
*p = qq; *p = qq;
*allocated = bn; *allocated = bn;

View File

@@ -488,6 +488,8 @@ static int merge_env_file_push(
free_and_replace(value, expanded_value); free_and_replace(value, expanded_value);
log_debug("%s:%u: setting %s=%s", filename, line, key, value);
return load_env_file_push(filename, line, key, value, env, n_pushed); return load_env_file_push(filename, line, key, value, env, n_pushed);
} }

View File

@@ -30,8 +30,6 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
assert(p); assert(p);
assert(ret); assert(ret);
/* Those two don't make sense together. */
assert(!FLAGS_SET(flags, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE));
/* Bail early if called after last value or with no input */ /* Bail early if called after last value or with no input */
if (!*p) if (!*p)

View File

@@ -942,10 +942,10 @@ int warn_file_is_world_accessible(const char *filename, struct stat *st, const c
if (unit) if (unit)
log_syntax(unit, LOG_WARNING, filename, line, 0, log_syntax(unit, LOG_WARNING, filename, line, 0,
"%s has %04o mode that is too permissive, please adjust the access mode.", "%s has %04o mode that is too permissive, please adjust the ownership and access mode.",
filename, st->st_mode & 07777); filename, st->st_mode & 07777);
else else
log_warning("%s has %04o mode that is too permissive, please adjust the access mode.", log_warning("%s has %04o mode that is too permissive, please adjust the ownership and access mode.",
filename, st->st_mode & 07777); filename, st->st_mode & 07777);
return 0; return 0;
} }

View File

@@ -741,7 +741,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
* process. On each iteration, we move one component from "todo" to "done", processing it's special meaning * process. On each iteration, we move one component from "todo" to "done", processing it's special meaning
* each time. The "todo" path always starts with at least one slash, the "done" path always ends in no * each time. The "todo" path always starts with at least one slash, the "done" path always ends in no
* slash. We always keep an O_PATH fd to the component we are currently processing, thus keeping lookup races * slash. We always keep an O_PATH fd to the component we are currently processing, thus keeping lookup races
* at a minimum. * to a minimum.
* *
* Suggested usage: whenever you want to canonicalize a path, use this function. Pass the absolute path you got * Suggested usage: whenever you want to canonicalize a path, use this function. Pass the absolute path you got
* as-is: fully qualified and relative to your host's root. Optionally, specify the root parameter to tell this * as-is: fully qualified and relative to your host's root. Optionally, specify the root parameter to tell this
@@ -751,9 +751,9 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
* There are three ways to invoke this function: * There are three ways to invoke this function:
* *
* 1. Without CHASE_STEP or CHASE_OPEN: in this case the path is resolved and the normalized path is returned * 1. Without CHASE_STEP or CHASE_OPEN: in this case the path is resolved and the normalized path is returned
* in `ret`. The return value is < 0 on error. If CHASE_NONEXISTENT is also set 0 is returned if the file * in `ret`. The return value is < 0 on error. If CHASE_NONEXISTENT is also set, 0 is returned if the file
* doesn't exist, > 0 otherwise. If CHASE_NONEXISTENT is not set >= 0 is returned if the destination was * doesn't exist, > 0 otherwise. If CHASE_NONEXISTENT is not set, >= 0 is returned if the destination was
* found, -ENOENT if it doesn't. * found, -ENOENT if it wasn't.
* *
* 2. With CHASE_OPEN: in this case the destination is opened after chasing it as O_PATH and this file * 2. With CHASE_OPEN: in this case the destination is opened after chasing it as O_PATH and this file
* descriptor is returned as return value. This is useful to open files relative to some root * descriptor is returned as return value. This is useful to open files relative to some root
@@ -769,13 +769,13 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
* *
* 4. With CHASE_SAFE: in this case the path must not contain unsafe transitions, i.e. transitions from * 4. With CHASE_SAFE: in this case the path must not contain unsafe transitions, i.e. transitions from
* unprivileged to privileged files or directories. In such cases the return value is -ENOLINK. If * unprivileged to privileged files or directories. In such cases the return value is -ENOLINK. If
* CHASE_WARN is also set a warning describing the unsafe transition is emitted. * CHASE_WARN is also set, a warning describing the unsafe transition is emitted.
* *
* 5. With CHASE_NO_AUTOFS: in this case if an autofs mount point is encountered, the path normalization is * 5. With CHASE_NO_AUTOFS: in this case if an autofs mount point is encountered, path normalization
* aborted and -EREMOTE is returned. If CHASE_WARN is also set a warning showing the path of the mount point * is aborted and -EREMOTE is returned. If CHASE_WARN is also set, a warning showing the path of
* is emitted. * the mount point is emitted.
* *
* */ */
/* A root directory of "/" or "" is identical to none */ /* A root directory of "/" or "" is identical to none */
if (empty_or_root(original_root)) if (empty_or_root(original_root))
@@ -1307,6 +1307,17 @@ int fsync_directory_of_file(int fd) {
return 0; return 0;
} }
int fsync_full(int fd) {
int r, q;
/* Sync both the file and the directory */
r = fsync(fd) < 0 ? -errno : 0;
q = fsync_directory_of_file(fd);
return r < 0 ? r : q;
}
int fsync_path_at(int at_fd, const char *path) { int fsync_path_at(int at_fd, const char *path) {
_cleanup_close_ int opened_fd = -1; _cleanup_close_ int opened_fd = -1;
int fd; int fd;

View File

@@ -74,14 +74,16 @@ union inotify_event_buffer {
int inotify_add_watch_fd(int fd, int what, uint32_t mask); int inotify_add_watch_fd(int fd, int what, uint32_t mask);
enum { enum {
CHASE_PREFIX_ROOT = 1 << 0, /* If set, the specified path will be prefixed by the specified root before beginning the iteration */ CHASE_PREFIX_ROOT = 1 << 0, /* The specified path will be prefixed by the specified root before beginning the iteration */
CHASE_NONEXISTENT = 1 << 1, /* If set, it's OK if the path doesn't actually exist. */ CHASE_NONEXISTENT = 1 << 1, /* It's OK if the path doesn't actually exist. */
CHASE_NO_AUTOFS = 1 << 2, /* If set, return -EREMOTE if autofs mount point found */ CHASE_NO_AUTOFS = 1 << 2, /* Return -EREMOTE if autofs mount point found */
CHASE_SAFE = 1 << 3, /* If set, return EPERM if we ever traverse from unprivileged to privileged files or directories */ CHASE_SAFE = 1 << 3, /* Return EPERM if we ever traverse from unprivileged to privileged files or directories */
CHASE_OPEN = 1 << 4, /* If set, return an O_PATH object to the final component */ CHASE_OPEN = 1 << 4, /* Return an O_PATH object to the final component */
CHASE_TRAIL_SLASH = 1 << 5, /* If set, any trailing slash will be preserved */ CHASE_TRAIL_SLASH = 1 << 5, /* Any trailing slash will be preserved */
CHASE_STEP = 1 << 6, /* If set, just execute a single step of the normalization */ CHASE_STEP = 1 << 6, /* Just execute a single step of the normalization */
CHASE_NOFOLLOW = 1 << 7, /* Only valid with CHASE_OPEN: when the path's right-most component refers to symlink return O_PATH fd of the symlink, rather than following it. */ CHASE_NOFOLLOW = 1 << 7, /* Do not follow the path's right-most compontent. With CHASE_OPEN, when
* the path's right-most component refers to symlink, return O_PATH fd of
* the symlink. */
CHASE_WARN = 1 << 8, /* Emit an appropriate warning when an error is encountered */ CHASE_WARN = 1 << 8, /* Emit an appropriate warning when an error is encountered */
}; };
@@ -114,6 +116,7 @@ void unlink_tempfilep(char (*p)[]);
int unlinkat_deallocate(int fd, const char *name, int flags); int unlinkat_deallocate(int fd, const char *name, int flags);
int fsync_directory_of_file(int fd); int fsync_directory_of_file(int fd);
int fsync_full(int fd);
int fsync_path_at(int at_fd, const char *path); int fsync_path_at(int at_fd, const char *path);
int syncfs_path(int atfd, const char *path); int syncfs_path(int atfd, const char *path);

View File

@@ -12,30 +12,38 @@
#if 0 /* NM_IGNORED */ #if 0 /* NM_IGNORED */
#define PATH_SPLIT_SBIN_BIN(x) x "sbin:" x "bin" #define PATH_SPLIT_SBIN_BIN(x) x "sbin:" x "bin"
#define PATH_SPLIT_BIN_SBIN(x) x "bin:" x "sbin"
#define PATH_SPLIT_SBIN_BIN_NULSTR(x) x "sbin\0" x "bin\0" #define PATH_SPLIT_SBIN_BIN_NULSTR(x) x "sbin\0" x "bin\0"
#define PATH_NORMAL_SBIN_BIN(x) x "bin" #define PATH_NORMAL_SBIN_BIN(x) x "bin"
#define PATH_NORMAL_BIN_SBIN(x) x "bin"
#define PATH_NORMAL_SBIN_BIN_NULSTR(x) x "bin\0" #define PATH_NORMAL_SBIN_BIN_NULSTR(x) x "bin\0"
#if HAVE_SPLIT_BIN #if HAVE_SPLIT_BIN
# define PATH_SBIN_BIN(x) PATH_SPLIT_SBIN_BIN(x) # define PATH_SBIN_BIN(x) PATH_SPLIT_SBIN_BIN(x)
# define PATH_BIN_SBIN(x) PATH_SPLIT_BIN_SBIN(x)
# define PATH_SBIN_BIN_NULSTR(x) PATH_SPLIT_SBIN_BIN_NULSTR(x) # define PATH_SBIN_BIN_NULSTR(x) PATH_SPLIT_SBIN_BIN_NULSTR(x)
#else #else
# define PATH_SBIN_BIN(x) PATH_NORMAL_SBIN_BIN(x) # define PATH_SBIN_BIN(x) PATH_NORMAL_SBIN_BIN(x)
# define PATH_BIN_SBIN(x) PATH_NORMAL_BIN_SBIN(x)
# define PATH_SBIN_BIN_NULSTR(x) PATH_NORMAL_SBIN_BIN_NULSTR(x) # define PATH_SBIN_BIN_NULSTR(x) PATH_NORMAL_SBIN_BIN_NULSTR(x)
#endif #endif
#define DEFAULT_PATH_NORMAL PATH_SBIN_BIN("/usr/local/") ":" PATH_SBIN_BIN("/usr/") #define DEFAULT_PATH_NORMAL PATH_SBIN_BIN("/usr/local/") ":" PATH_SBIN_BIN("/usr/")
#define DEFAULT_USER_PATH_NORMAL PATH_BIN_SBIN("/usr/local/") ":" PATH_BIN_SBIN("/usr/")
#define DEFAULT_PATH_NORMAL_NULSTR PATH_SBIN_BIN_NULSTR("/usr/local/") PATH_SBIN_BIN_NULSTR("/usr/") #define DEFAULT_PATH_NORMAL_NULSTR PATH_SBIN_BIN_NULSTR("/usr/local/") PATH_SBIN_BIN_NULSTR("/usr/")
#define DEFAULT_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":" PATH_SBIN_BIN("/") #define DEFAULT_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":" PATH_SBIN_BIN("/")
#define DEFAULT_USER_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":" PATH_BIN_SBIN("/")
#define DEFAULT_PATH_SPLIT_USR_NULSTR DEFAULT_PATH_NORMAL_NULSTR PATH_SBIN_BIN_NULSTR("/") #define DEFAULT_PATH_SPLIT_USR_NULSTR DEFAULT_PATH_NORMAL_NULSTR PATH_SBIN_BIN_NULSTR("/")
#define DEFAULT_PATH_COMPAT PATH_SPLIT_SBIN_BIN("/usr/local/") ":" PATH_SPLIT_SBIN_BIN("/usr/") ":" PATH_SPLIT_SBIN_BIN("/") #define DEFAULT_PATH_COMPAT PATH_SPLIT_SBIN_BIN("/usr/local/") ":" PATH_SPLIT_SBIN_BIN("/usr/") ":" PATH_SPLIT_SBIN_BIN("/")
#if HAVE_SPLIT_USR #if HAVE_SPLIT_USR
# define DEFAULT_PATH DEFAULT_PATH_SPLIT_USR # define DEFAULT_PATH DEFAULT_PATH_SPLIT_USR
# define DEFAULT_USER_PATH DEFAULT_USER_PATH_SPLIT_USR
# define DEFAULT_PATH_NULSTR DEFAULT_PATH_SPLIT_USR_NULSTR # define DEFAULT_PATH_NULSTR DEFAULT_PATH_SPLIT_USR_NULSTR
#else #else
# define DEFAULT_PATH DEFAULT_PATH_NORMAL # define DEFAULT_PATH DEFAULT_PATH_NORMAL
# define DEFAULT_USER_PATH DEFAULT_USER_PATH_NORMAL
# define DEFAULT_PATH_NULSTR DEFAULT_PATH_NORMAL_NULSTR # define DEFAULT_PATH_NULSTR DEFAULT_PATH_NORMAL_NULSTR
#endif #endif
#endif /* NM_IGNORED */ #endif /* NM_IGNORED */

View File

@@ -27,8 +27,10 @@
#include "alloc-util.h" #include "alloc-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h"
#include "io-util.h" #include "io-util.h"
#include "missing.h" #include "missing.h"
#include "parse-util.h"
#include "random-util.h" #include "random-util.h"
#include "siphash24.h" #include "siphash24.h"
#include "time-util.h" #include "time-util.h"
@@ -398,3 +400,28 @@ void random_bytes(void *p, size_t n) {
/* 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. */
pseudo_random_bytes(p, n); pseudo_random_bytes(p, n);
} }
#if 0 /* NM_IGNORED */
size_t random_pool_size(void) {
_cleanup_free_ char *s = NULL;
int r;
/* Read pool size, if possible */
r = read_one_line_file("/proc/sys/kernel/random/poolsize", &s);
if (r < 0)
log_debug_errno(r, "Failed to read pool size from kernel: %m");
else {
unsigned sz;
r = safe_atou(s, &sz);
if (r < 0)
log_debug_errno(r, "Failed to parse pool size: %s", s);
else
/* poolsize is in bits on 2.6, but we want bytes */
return CLAMP(sz / 8, RANDOM_POOL_SIZE_MIN, RANDOM_POOL_SIZE_MAX);
}
/* Use the minimum as default, if we can't retrieve the correct value */
return RANDOM_POOL_SIZE_MIN;
}
#endif /* NM_IGNORED */

View File

@@ -31,3 +31,9 @@ static inline uint32_t random_u32(void) {
} }
int rdrand(unsigned long *ret); int rdrand(unsigned long *ret);
/* Some limits on the pool sizes when we deal with the kernel random pool */
#define RANDOM_POOL_SIZE_MIN 512U
#define RANDOM_POOL_SIZE_MAX (10U*1024U*1024U)
size_t random_pool_size(void);

View File

@@ -157,6 +157,18 @@ void strv_print(char **l);
_found; \ _found; \
}) })
#define ENDSWITH_SET(p, ...) \
({ \
const char *_p = (p); \
char *_found = NULL, **_i; \
STRV_FOREACH(_i, STRV_MAKE(__VA_ARGS__)) { \
_found = endswith(_p, *_i); \
if (_found) \
break; \
} \
_found; \
})
#define FOREACH_STRING(x, y, ...) \ #define FOREACH_STRING(x, y, ...) \
for (char **_l = STRV_MAKE(({ x = y; }), ##__VA_ARGS__); \ for (char **_l = STRV_MAKE(({ x = y; }), ##__VA_ARGS__); \
x; \ x; \

View File

@@ -1196,7 +1196,10 @@ bool ntp_synced(void) {
if (adjtimex(&txc) < 0) if (adjtimex(&txc) < 0)
return false; return false;
if (txc.status & STA_UNSYNC) /* Consider the system clock synchronized if the reported maximum error is smaller than the maximum
* value (16 seconds). Ignore the STA_UNSYNC flag as it may have been set to prevent the kernel from
* touching the RTC. */
if (txc.maxerror >= 16000000)
return false; return false;
return true; return true;
@@ -1421,8 +1424,8 @@ struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc) {
return utc ? gmtime_r(t, tm) : localtime_r(t, tm); return utc ? gmtime_r(t, tm) : localtime_r(t, tm);
} }
unsigned long usec_to_jiffies(usec_t u) { static uint32_t sysconf_clock_ticks_cached(void) {
static thread_local unsigned long hz = 0; static thread_local uint32_t hz = 0;
long r; long r;
if (hz == 0) { if (hz == 0) {
@@ -1432,7 +1435,17 @@ unsigned long usec_to_jiffies(usec_t u) {
hz = r; hz = r;
} }
return DIV_ROUND_UP(u , USEC_PER_SEC / hz); return hz;
}
uint32_t usec_to_jiffies(usec_t u) {
uint32_t hz = sysconf_clock_ticks_cached();
return DIV_ROUND_UP(u, USEC_PER_SEC / hz);
}
usec_t jiffies_to_usec(uint32_t j) {
uint32_t hz = sysconf_clock_ticks_cached();
return DIV_ROUND_UP(j * USEC_PER_SEC, hz);
} }
usec_t usec_shift_clock(usec_t x, clockid_t from, clockid_t to) { usec_t usec_shift_clock(usec_t x, clockid_t from, clockid_t to) {

View File

@@ -136,7 +136,8 @@ int get_timezone(char **timezone);
time_t mktime_or_timegm(struct tm *tm, bool utc); time_t mktime_or_timegm(struct tm *tm, bool utc);
struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc); struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc);
unsigned long usec_to_jiffies(usec_t usec); uint32_t usec_to_jiffies(usec_t usec);
usec_t jiffies_to_usec(uint32_t jiffies);
bool in_utc_timezone(void); bool in_utc_timezone(void);

View File

@@ -58,6 +58,9 @@ struct sd_dhcp_lease {
struct in_addr *ntp; struct in_addr *ntp;
size_t ntp_size; size_t ntp_size;
struct in_addr *sip;
size_t sip_size;
struct sd_dhcp_route *static_route; struct sd_dhcp_route *static_route;
size_t static_route_size, static_route_allocated; size_t static_route_size, static_route_allocated;

View File

@@ -29,7 +29,7 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
case SD_DHCP_OPTION_PAD: case SD_DHCP_OPTION_PAD:
case SD_DHCP_OPTION_END: case SD_DHCP_OPTION_END:
if (size < *offset + 1) if (*offset + 1 > size)
return -ENOBUFS; return -ENOBUFS;
options[*offset] = code; options[*offset] = code;
@@ -37,42 +37,57 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
break; break;
case SD_DHCP_OPTION_USER_CLASS: { case SD_DHCP_OPTION_USER_CLASS: {
size_t len = 0; size_t total = 0;
char **s; char **s;
STRV_FOREACH(s, (char **) optval)
len += strlen(*s) + 1;
if (size < *offset + len + 2)
return -ENOBUFS;
options[*offset] = code;
options[*offset + 1] = len;
*offset += 2;
STRV_FOREACH(s, (char **) optval) { STRV_FOREACH(s, (char **) optval) {
len = strlen(*s); size_t len = strlen(*s);
if (len > 255) if (len > 255)
return -ENAMETOOLONG; return -ENAMETOOLONG;
total += 1 + len;
}
if (*offset + 2 + total > size)
return -ENOBUFS;
options[*offset] = code;
options[*offset + 1] = total;
*offset += 2;
STRV_FOREACH(s, (char **) optval) {
size_t len = strlen(*s);
options[*offset] = len; options[*offset] = len;
memcpy_safe(&options[*offset + 1], *s, len); memcpy(&options[*offset + 1], *s, len);
*offset += len + 1; *offset += 1 + len;
} }
break; break;
} }
case SD_DHCP_OPTION_SIP_SERVER:
if (*offset + 3 + optlen > size)
return -ENOBUFS;
options[*offset] = code;
options[*offset + 1] = optlen + 1;
options[*offset + 2] = 1;
memcpy_safe(&options[*offset + 3], optval, optlen);
*offset += 3 + optlen;
break;
default: default:
if (size < *offset + optlen + 2) if (*offset + 2 + optlen > size)
return -ENOBUFS; return -ENOBUFS;
options[*offset] = code; options[*offset] = code;
options[*offset + 1] = optlen; options[*offset + 1] = optlen;
memcpy_safe(&options[*offset + 2], optval, optlen); memcpy_safe(&options[*offset + 2], optval, optlen);
*offset += optlen + 2; *offset += 2 + optlen;
break; break;
} }
@@ -83,22 +98,25 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset,
uint8_t overload, uint8_t overload,
uint8_t code, size_t optlen, const void *optval) { uint8_t code, size_t optlen, const void *optval) {
size_t file_offset = 0, sname_offset =0; const bool use_file = overload & DHCP_OVERLOAD_FILE;
bool file, sname; const bool use_sname = overload & DHCP_OVERLOAD_SNAME;
int r; int r;
assert(message); assert(message);
assert(offset); assert(offset);
file = overload & DHCP_OVERLOAD_FILE; /* If *offset is in range [0, size), we are writing to ->options,
sname = overload & DHCP_OVERLOAD_SNAME; * if *offset is in range [size, size + sizeof(message->file)) and use_file, we are writing to ->file,
* if *offset is in range [size + use_file*sizeof(message->file), size + use_file*sizeof(message->file) + sizeof(message->sname))
* and use_sname, we are writing to ->sname.
*/
if (*offset < size) { if (*offset < size) {
/* still space in the options array */ /* still space in the options array */
r = option_append(message->options, size, offset, code, optlen, optval); r = option_append(message->options, size, offset, code, optlen, optval);
if (r >= 0) if (r >= 0)
return 0; return 0;
else if (r == -ENOBUFS && (file || sname)) { else if (r == -ENOBUFS && (use_file || use_sname)) {
/* did not fit, but we have more buffers to try /* did not fit, but we have more buffers to try
close the options array and move the offset to its end */ close the options array and move the offset to its end */
r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL); r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL);
@@ -110,8 +128,8 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset,
return r; return r;
} }
if (overload & DHCP_OVERLOAD_FILE) { if (use_file) {
file_offset = *offset - size; size_t file_offset = *offset - size;
if (file_offset < sizeof(message->file)) { if (file_offset < sizeof(message->file)) {
/* still space in the 'file' array */ /* still space in the 'file' array */
@@ -119,7 +137,7 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset,
if (r >= 0) { if (r >= 0) {
*offset = size + file_offset; *offset = size + file_offset;
return 0; return 0;
} else if (r == -ENOBUFS && sname) { } else if (r == -ENOBUFS && use_sname) {
/* did not fit, but we have more buffers to try /* did not fit, but we have more buffers to try
close the file array and move the offset to its end */ close the file array and move the offset to its end */
r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL); r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL);
@@ -132,19 +150,18 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset,
} }
} }
if (overload & DHCP_OVERLOAD_SNAME) { if (use_sname) {
sname_offset = *offset - size - (file ? sizeof(message->file) : 0); size_t sname_offset = *offset - size - use_file*sizeof(message->file);
if (sname_offset < sizeof(message->sname)) { if (sname_offset < sizeof(message->sname)) {
/* still space in the 'sname' array */ /* still space in the 'sname' array */
r = option_append(message->sname, sizeof(message->sname), &sname_offset, code, optlen, optval); r = option_append(message->sname, sizeof(message->sname), &sname_offset, code, optlen, optval);
if (r >= 0) { if (r >= 0) {
*offset = size + (file ? sizeof(message->file) : 0) + sname_offset; *offset = size + use_file*sizeof(message->file) + sname_offset;
return 0; return 0;
} else { } else
/* no space, or other error, give up */ /* no space, or other error, give up */
return r; return r;
}
} }
} }

View File

@@ -257,7 +257,7 @@ int config_parse_match_strv(
for (;;) { for (;;) {
_cleanup_free_ char *word = NULL, *k = NULL; _cleanup_free_ char *word = NULL, *k = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
if (r == 0) if (r == 0)
return 0; return 0;
if (r == -ENOMEM) if (r == -ENOMEM)

View File

@@ -1000,15 +1000,14 @@ static int client_send_request(sd_dhcp_client *client) {
if (r < 0) if (r < 0)
return r; return r;
if (client->state == DHCP_STATE_RENEWING) { if (client->state == DHCP_STATE_RENEWING)
r = dhcp_network_send_udp_socket(client->fd, r = dhcp_network_send_udp_socket(client->fd,
client->lease->server_address, client->lease->server_address,
DHCP_PORT_SERVER, DHCP_PORT_SERVER,
&request->dhcp, &request->dhcp,
sizeof(DHCPMessage) + optoffset); sizeof(DHCPMessage) + optoffset);
} else { else
r = dhcp_client_send_raw(client, request, sizeof(DHCPPacket) + optoffset); r = dhcp_client_send_raw(client, request, sizeof(DHCPPacket) + optoffset);
}
if (r < 0) if (r < 0)
return r; return r;
@@ -1216,7 +1215,7 @@ static int client_initialize_time_events(sd_dhcp_client *client) {
assert(client); assert(client);
assert(client->event); assert(client->event);
if (client->start_delay) { if (client->start_delay > 0) {
assert_se(sd_event_now(client->event, clock_boottime_or_monotonic(), &usec) >= 0); assert_se(sd_event_now(client->event, clock_boottime_or_monotonic(), &usec) >= 0);
usec += client->start_delay; usec += client->start_delay;
} }
@@ -1887,6 +1886,17 @@ static int client_receive_message_raw(
return client_handle_message(client, &packet->dhcp, len); return client_handle_message(client, &packet->dhcp, len);
} }
int sd_dhcp_client_send_renew(sd_dhcp_client *client) {
assert_return(client, -EINVAL);
assert_return(client->fd >= 0, -EINVAL);
client->start_delay = 0;
client->attempt = 1;
client->state = DHCP_STATE_RENEWING;
return client_initialize_time_events(client);
}
int sd_dhcp_client_start(sd_dhcp_client *client) { int sd_dhcp_client_start(sd_dhcp_client *client) {
int r; int r;

View File

@@ -122,6 +122,17 @@ int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr) {
return (int) lease->ntp_size; return (int) lease->ntp_size;
} }
int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr) {
assert_return(lease, -EINVAL);
assert_return(addr, -EINVAL);
if (lease->sip_size <= 0)
return -ENODATA;
*addr = lease->sip;
return (int) lease->sip_size;
}
int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) { int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) {
assert_return(lease, -EINVAL); assert_return(lease, -EINVAL);
assert_return(domainname, -EINVAL); assert_return(domainname, -EINVAL);
@@ -271,6 +282,7 @@ static sd_dhcp_lease *dhcp_lease_free(sd_dhcp_lease *lease) {
free(lease->domainname); free(lease->domainname);
free(lease->dns); free(lease->dns);
free(lease->ntp); free(lease->ntp);
free(lease->sip);
free(lease->static_route); free(lease->static_route);
free(lease->client_id); free(lease->client_id);
free(lease->vendor_specific); free(lease->vendor_specific);
@@ -404,6 +416,36 @@ static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_add
return 0; return 0;
} }
static int lease_parse_sip_server(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) {
assert(option);
assert(ret);
assert(n_ret);
if (len <= 0) {
*ret = mfree(*ret);
*n_ret = 0;
} else {
size_t n_addresses;
struct in_addr *addresses;
int l = len - 1;
if (l % 4 != 0)
return -EINVAL;
n_addresses = l / 4;
addresses = newdup(struct in_addr, option + 1, n_addresses);
if (!addresses)
return -ENOMEM;
free(*ret);
*ret = addresses;
*n_ret = n_addresses;
}
return 0;
}
static int lease_parse_routes( static int lease_parse_routes(
const uint8_t *option, size_t len, const uint8_t *option, size_t len,
struct sd_dhcp_route **routes, size_t *routes_size, size_t *routes_allocated) { struct sd_dhcp_route **routes, size_t *routes_size, size_t *routes_allocated) {
@@ -557,6 +599,12 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
log_debug_errno(r, "Failed to parse NTP server, ignoring: %m"); log_debug_errno(r, "Failed to parse NTP server, ignoring: %m");
break; break;
case SD_DHCP_OPTION_SIP_SERVER:
r = lease_parse_sip_server(option, len, &lease->sip, &lease->sip_size);
if (r < 0)
log_debug_errno(r, "Failed to parse SIP server, ignoring: %m");
break;
case SD_DHCP_OPTION_STATIC_ROUTE: case SD_DHCP_OPTION_STATIC_ROUTE:
r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size, &lease->static_route_allocated); r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size, &lease->static_route_allocated);
if (r < 0) if (r < 0)
@@ -895,6 +943,13 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
fputc('\n', f); fputc('\n', f);
} }
r = sd_dhcp_lease_get_sip(lease, &addresses);
if (r > 0) {
fputs("SIP=", f);
serialize_in_addrs(f, addresses, r, false, NULL);
fputc('\n', f);
}
r = sd_dhcp_lease_get_domainname(lease, &string); r = sd_dhcp_lease_get_domainname(lease, &string);
if (r >= 0) if (r >= 0)
fprintf(f, "DOMAINNAME=%s\n", string); fprintf(f, "DOMAINNAME=%s\n", string);
@@ -985,6 +1040,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
*broadcast = NULL, *broadcast = NULL,
*dns = NULL, *dns = NULL,
*ntp = NULL, *ntp = NULL,
*sip = NULL,
*mtu = NULL, *mtu = NULL,
*routes = NULL, *routes = NULL,
*domains = NULL, *domains = NULL,
@@ -1013,6 +1069,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
"BROADCAST", &broadcast, "BROADCAST", &broadcast,
"DNS", &dns, "DNS", &dns,
"NTP", &ntp, "NTP", &ntp,
"SIP", &sip,
"MTU", &mtu, "MTU", &mtu,
"DOMAINNAME", &lease->domainname, "DOMAINNAME", &lease->domainname,
"HOSTNAME", &lease->hostname, "HOSTNAME", &lease->hostname,
@@ -1117,6 +1174,14 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
lease->ntp_size = r; lease->ntp_size = r;
} }
if (sip) {
r = deserialize_in_addrs(&lease->sip, sip);
if (r < 0)
log_debug_errno(r, "Failed to deserialize SIP servers %s, ignoring: %m", sip);
else
lease->ntp_size = r;
}
if (mtu) { if (mtu) {
r = safe_atou16(mtu, &lease->mtu); r = safe_atou16(mtu, &lease->mtu);
if (r < 0) if (r < 0)

View File

@@ -31,6 +31,9 @@
#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN #define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
#define IRT_DEFAULT (1 * USEC_PER_DAY)
#define IRT_MINIMUM (600 * USEC_PER_SEC)
/* what to request from the server, addresses (IA_NA) and/or prefixes (IA_PD) */ /* what to request from the server, addresses (IA_NA) and/or prefixes (IA_PD) */
enum { enum {
DHCP6_REQUEST_IA_NA = 1, DHCP6_REQUEST_IA_NA = 1,
@@ -73,6 +76,8 @@ struct sd_dhcp6_client {
void *userdata; void *userdata;
struct duid duid; struct duid duid;
size_t duid_len; size_t duid_len;
usec_t information_request_time_usec;
usec_t information_refresh_time_usec;
}; };
static const uint16_t default_req_opts[] = { static const uint16_t default_req_opts[] = {
@@ -826,6 +831,7 @@ static int client_parse_message(
uint32_t lt_t1 = ~0, lt_t2 = ~0; uint32_t lt_t1 = ~0, lt_t2 = ~0;
bool clientid = false; bool clientid = false;
size_t pos = 0; size_t pos = 0;
usec_t irt = IRT_DEFAULT;
int r; int r;
assert(client); assert(client);
@@ -1000,6 +1006,13 @@ static int client_parse_message(
return r; return r;
break; break;
case SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME:
if (optlen != 4)
return -EINVAL;
irt = unaligned_read_be32((be32_t *) optval) * USEC_PER_SEC;
break;
} }
pos += offsetof(DHCP6Option, data) + optlen; pos += offsetof(DHCP6Option, data) + optlen;
@@ -1031,6 +1044,8 @@ static int client_parse_message(
} }
} }
client->information_refresh_time_usec = MAX(irt, IRT_MINIMUM);
return 0; return 0;
} }
@@ -1431,8 +1446,15 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) {
client->fd = r; client->fd = r;
} }
if (client->information_request) if (client->information_request) {
usec_t t = now(CLOCK_MONOTONIC);
if (t < usec_add(client->information_request_time_usec, client->information_refresh_time_usec))
return 0;
client->information_request_time_usec = t;
state = DHCP6_STATE_INFORMATION_REQUEST; state = DHCP6_STATE_INFORMATION_REQUEST;
}
log_dhcp6_client(client, "Started in %s mode", log_dhcp6_client(client, "Started in %s mode",
client->information_request? "Information request": client->information_request? "Information request":

View File

@@ -87,6 +87,7 @@ enum {
SD_DHCP_OPTION_NEW_POSIX_TIMEZONE = 100, SD_DHCP_OPTION_NEW_POSIX_TIMEZONE = 100,
SD_DHCP_OPTION_NEW_TZDB_TIMEZONE = 101, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE = 101,
SD_DHCP_OPTION_DOMAIN_SEARCH_LIST = 119, SD_DHCP_OPTION_DOMAIN_SEARCH_LIST = 119,
SD_DHCP_OPTION_SIP_SERVER = 120,
SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE = 121, SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE = 121,
SD_DHCP_OPTION_PRIVATE_BASE = 224, SD_DHCP_OPTION_PRIVATE_BASE = 224,
/* Windows 10 option to send when Anonymize=true */ /* Windows 10 option to send when Anonymize=true */
@@ -177,6 +178,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); int sd_dhcp_client_send_release(sd_dhcp_client *client);
int sd_dhcp_client_send_renew(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);

View File

@@ -44,6 +44,7 @@ int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr);
int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr);
int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu); int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu);
int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname); int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname);
int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains); int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains);

View File

@@ -66,6 +66,7 @@ enum {
SD_DHCP6_OPTION_IA_PD_PREFIX = 26, /* RFC 3633, prefix delegation */ SD_DHCP6_OPTION_IA_PD_PREFIX = 26, /* RFC 3633, prefix delegation */
SD_DHCP6_OPTION_SNTP_SERVERS = 31, /* RFC 4075, deprecated */ SD_DHCP6_OPTION_SNTP_SERVERS = 31, /* RFC 4075, deprecated */
SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME = 32, /* RFC 8415, sec. 21.23 */
/* option code 35 is unassigned */ /* option code 35 is unassigned */