summaryrefslogtreecommitdiff
path: root/src/systemd
diff options
context:
space:
mode:
Diffstat (limited to 'src/systemd')
-rw-r--r--src/systemd/sd-adapt/nm-sd-adapt.h2
-rw-r--r--src/systemd/src/basic/alloc-util.h12
-rw-r--r--src/systemd/src/basic/escape.c4
-rw-r--r--src/systemd/src/basic/ether-addr-util.c42
-rw-r--r--src/systemd/src/basic/ether-addr-util.h11
-rw-r--r--src/systemd/src/basic/fd-util.c25
-rw-r--r--src/systemd/src/basic/fd-util.h4
-rw-r--r--src/systemd/src/basic/fileio.c13
-rw-r--r--src/systemd/src/basic/fs-util.c34
-rw-r--r--src/systemd/src/basic/fs-util.h1
-rw-r--r--src/systemd/src/basic/hashmap.c2
-rw-r--r--src/systemd/src/basic/hexdecoct.c78
-rw-r--r--src/systemd/src/basic/io-util.h9
-rw-r--r--src/systemd/src/basic/mempool.c11
-rw-r--r--src/systemd/src/basic/mempool.h2
-rw-r--r--src/systemd/src/basic/parse-util.c43
-rw-r--r--src/systemd/src/basic/parse-util.h3
-rw-r--r--src/systemd/src/basic/path-util.c3
-rw-r--r--src/systemd/src/basic/path-util.h3
-rw-r--r--src/systemd/src/basic/process-util.c17
-rw-r--r--src/systemd/src/basic/process-util.h4
-rw-r--r--src/systemd/src/basic/random-util.c2
-rw-r--r--src/systemd/src/basic/set.h2
-rw-r--r--src/systemd/src/basic/signal-util.h2
-rw-r--r--src/systemd/src/basic/stat-util.c292
-rw-r--r--src/systemd/src/basic/stat-util.h67
-rw-r--r--src/systemd/src/basic/string-util.c46
-rw-r--r--src/systemd/src/basic/string-util.h4
-rw-r--r--src/systemd/src/basic/strv.c34
-rw-r--r--src/systemd/src/basic/strv.h6
-rw-r--r--src/systemd/src/basic/time-util.c59
-rw-r--r--src/systemd/src/basic/time-util.h2
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-identifier.c4
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-option.c29
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.c105
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.h9
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-client.c32
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-lease.c10
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp6-lease.c6
-rw-r--r--src/systemd/src/libsystemd-network/sd-lldp.c8
-rw-r--r--src/systemd/src/systemd/sd-dhcp-client.h4
41 files changed, 853 insertions, 193 deletions
diff --git a/src/systemd/sd-adapt/nm-sd-adapt.h b/src/systemd/sd-adapt/nm-sd-adapt.h
index 1ff2a345be..380cbc60e2 100644
--- a/src/systemd/sd-adapt/nm-sd-adapt.h
+++ b/src/systemd/sd-adapt/nm-sd-adapt.h
@@ -142,6 +142,8 @@ G_STMT_START { \
# endif
#endif
+#define VALGRIND 0
+
static inline pid_t
raw_getpid (void) {
#if defined(__alpha__)
diff --git a/src/systemd/src/basic/alloc-util.h b/src/systemd/src/basic/alloc-util.h
index 88cd6b0bc2..bae6a28451 100644
--- a/src/systemd/src/basic/alloc-util.h
+++ b/src/systemd/src/basic/alloc-util.h
@@ -18,9 +18,17 @@
#define new0(t, n) ((t*) calloc((n), sizeof(t)))
-#define newa(t, n) ((t*) alloca(sizeof(t)*(n)))
+#define newa(t, n) \
+ ({ \
+ assert(!size_multiply_overflow(sizeof(t), n)); \
+ (t*) alloca(sizeof(t)*(n)); \
+ })
-#define newa0(t, n) ((t*) alloca0(sizeof(t)*(n)))
+#define newa0(t, n) \
+ ({ \
+ assert(!size_multiply_overflow(sizeof(t), n)); \
+ (t*) alloca0(sizeof(t)*(n)); \
+ })
#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n)))
diff --git a/src/systemd/src/basic/escape.c b/src/systemd/src/basic/escape.c
index 53bfb4204a..f51de788f7 100644
--- a/src/systemd/src/basic/escape.c
+++ b/src/systemd/src/basic/escape.c
@@ -190,7 +190,7 @@ int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit)
/* C++11 style 16bit unicode */
int a[4];
- unsigned i;
+ size_t i;
uint32_t c;
if (length != (size_t) -1 && length < 5)
@@ -217,7 +217,7 @@ int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit)
/* C++11 style 32bit unicode */
int a[8];
- unsigned i;
+ size_t i;
char32_t c;
if (length != (size_t) -1 && length < 9)
diff --git a/src/systemd/src/basic/ether-addr-util.c b/src/systemd/src/basic/ether-addr-util.c
index cc16e059c5..75de9a1902 100644
--- a/src/systemd/src/basic/ether-addr-util.c
+++ b/src/systemd/src/basic/ether-addr-util.c
@@ -35,19 +35,23 @@ char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR
return buffer;
}
-bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b) {
+int ether_addr_compare(const void *a, const void *b) {
assert(a);
assert(b);
- return a->ether_addr_octet[0] == b->ether_addr_octet[0] &&
- a->ether_addr_octet[1] == b->ether_addr_octet[1] &&
- a->ether_addr_octet[2] == b->ether_addr_octet[2] &&
- a->ether_addr_octet[3] == b->ether_addr_octet[3] &&
- a->ether_addr_octet[4] == b->ether_addr_octet[4] &&
- a->ether_addr_octet[5] == b->ether_addr_octet[5];
+ return memcmp(a, b, ETH_ALEN);
}
-int ether_addr_from_string(const char *s, struct ether_addr *ret, size_t *offset) {
+static void ether_addr_hash_func(const void *p, struct siphash *state) {
+ siphash24_compress(p, sizeof(struct ether_addr), state);
+}
+
+const struct hash_ops ether_addr_hash_ops = {
+ .hash = ether_addr_hash_func,
+ .compare = ether_addr_compare
+};
+
+int ether_addr_from_string(const char *s, struct ether_addr *ret) {
size_t pos = 0, n, field;
char sep = '\0';
const char *hex = HEXDIGITS, *hexoff;
@@ -86,31 +90,35 @@ int ether_addr_from_string(const char *s, struct ether_addr *ret, size_t *offset
assert(s);
assert(ret);
+ s += strspn(s, WHITESPACE);
sep = s[strspn(s, hex)];
- if (sep == '\n')
- return -EINVAL;
- if (!strchr(":.-", sep))
- return -EINVAL;
if (sep == '.') {
uint16_t shorts[3] = { 0 };
parse_fields(shorts);
+ if (s[pos] != '\0')
+ return -EINVAL;
+
for (n = 0; n < ELEMENTSOF(shorts); n++) {
ret->ether_addr_octet[2*n] = ((shorts[n] & (uint16_t)0xff00) >> 8);
ret->ether_addr_octet[2*n + 1] = (shorts[n] & (uint16_t)0x00ff);
}
- } else {
- struct ether_addr out = { .ether_addr_octet = { 0 } };
+
+ } else if (IN_SET(sep, ':', '-')) {
+ struct ether_addr out = ETHER_ADDR_NULL;
parse_fields(out.ether_addr_octet);
+ if (s[pos] != '\0')
+ return -EINVAL;
+
for (n = 0; n < ELEMENTSOF(out.ether_addr_octet); n++)
ret->ether_addr_octet[n] = out.ether_addr_octet[n];
- }
- if (offset)
- *offset = pos;
+ } else
+ return -EINVAL;
+
return 0;
}
diff --git a/src/systemd/src/basic/ether-addr-util.h b/src/systemd/src/basic/ether-addr-util.h
index 29d7f36294..f7e0de54cc 100644
--- a/src/systemd/src/basic/ether-addr-util.h
+++ b/src/systemd/src/basic/ether-addr-util.h
@@ -10,13 +10,18 @@
#include <net/ethernet.h>
#include <stdbool.h>
+#include "hash-funcs.h"
+
#define ETHER_ADDR_FORMAT_STR "%02X%02X%02X%02X%02X%02X"
#define ETHER_ADDR_FORMAT_VAL(x) (x).ether_addr_octet[0], (x).ether_addr_octet[1], (x).ether_addr_octet[2], (x).ether_addr_octet[3], (x).ether_addr_octet[4], (x).ether_addr_octet[5]
#define ETHER_ADDR_TO_STRING_MAX (3*6)
char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]);
-bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b);
+int ether_addr_compare(const void *a, const void *b);
+static inline bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b) {
+ return ether_addr_compare(a, b) == 0;
+}
#define ETHER_ADDR_NULL ((const struct ether_addr){})
@@ -24,4 +29,6 @@ static inline bool ether_addr_is_null(const struct ether_addr *addr) {
return ether_addr_equal(addr, &ETHER_ADDR_NULL);
}
-int ether_addr_from_string(const char *s, struct ether_addr *ret, size_t *offset);
+int ether_addr_from_string(const char *s, struct ether_addr *ret);
+
+extern const struct hash_ops ether_addr_hash_ops;
diff --git a/src/systemd/src/basic/fd-util.c b/src/systemd/src/basic/fd-util.c
index 2668a0d1cd..6a753195df 100644
--- a/src/systemd/src/basic/fd-util.c
+++ b/src/systemd/src/basic/fd-util.c
@@ -87,8 +87,8 @@ void safe_close_pair(int p[]) {
p[1] = safe_close(p[1]);
}
-void close_many(const int fds[], unsigned n_fd) {
- unsigned i;
+void close_many(const int fds[], size_t n_fd) {
+ size_t i;
assert(fds || n_fd <= 0);
@@ -181,8 +181,8 @@ int fd_cloexec(int fd, bool cloexec) {
}
#if 0 /* NM_IGNORED */
-_pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
- unsigned i;
+_pure_ static bool fd_in_set(int fd, const int fdset[], size_t n_fdset) {
+ size_t i;
assert(n_fdset == 0 || fdset);
@@ -193,7 +193,7 @@ _pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
return false;
}
-int close_all_fds(const int except[], unsigned n_except) {
+int close_all_fds(const int except[], size_t n_except) {
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
int r = 0;
@@ -202,15 +202,22 @@ int close_all_fds(const int except[], unsigned n_except) {
d = opendir("/proc/self/fd");
if (!d) {
- int fd;
struct rlimit rl;
+ int fd, max_fd;
- /* When /proc isn't available (for example in chroots)
- * the fallback is brute forcing through the fd
+ /* When /proc isn't available (for example in chroots) the fallback is brute forcing through the fd
* table */
assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
- for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
+
+ if (rl.rlim_max == 0)
+ return -EINVAL;
+
+ /* Let's take special care if the resource limit is set to unlimited, or actually larger than the range
+ * of 'int'. Let's avoid implicit overflows. */
+ max_fd = (rl.rlim_max == RLIM_INFINITY || rl.rlim_max > INT_MAX) ? INT_MAX : (int) (rl.rlim_max - 1);
+
+ for (fd = 3; fd >= 0; fd = fd < max_fd ? fd + 1 : -1) {
int q;
if (fd_in_set(fd, except, n_except))
diff --git a/src/systemd/src/basic/fd-util.h b/src/systemd/src/basic/fd-util.h
index ded022f738..89c3f34c7b 100644
--- a/src/systemd/src/basic/fd-util.h
+++ b/src/systemd/src/basic/fd-util.h
@@ -29,7 +29,7 @@ static inline int safe_close_above_stdio(int fd) {
return safe_close(fd);
}
-void close_many(const int fds[], unsigned n_fd);
+void close_many(const int fds[], size_t n_fd);
int fclose_nointr(FILE *f);
FILE* safe_fclose(FILE *f);
@@ -59,7 +59,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir);
int fd_nonblock(int fd, bool nonblock);
int fd_cloexec(int fd, bool cloexec);
-int close_all_fds(const int except[], unsigned n_except);
+int close_all_fds(const int except[], size_t n_except);
int same_fd(int a, int b);
diff --git a/src/systemd/src/basic/fileio.c b/src/systemd/src/basic/fileio.c
index 9e037042d7..4f71384e39 100644
--- a/src/systemd/src/basic/fileio.c
+++ b/src/systemd/src/basic/fileio.c
@@ -53,6 +53,7 @@ int write_string_stream_ts(
struct timespec *ts) {
bool needs_nl;
+ int r;
assert(f);
assert(line);
@@ -77,6 +78,13 @@ int write_string_stream_ts(
if (fputc('\n', f) == EOF)
return -errno;
+ if (flags & WRITE_STRING_FILE_SYNC)
+ r = fflush_sync_and_check(f);
+ else
+ r = fflush_and_check(f);
+ if (r < 0)
+ return r;
+
if (ts) {
struct timespec twice[2] = {*ts, *ts};
@@ -84,10 +92,7 @@ int write_string_stream_ts(
return -errno;
}
- if (flags & WRITE_STRING_FILE_SYNC)
- return fflush_sync_and_check(f);
- else
- return fflush_and_check(f);
+ return 0;
}
static int write_string_file_atomic(
diff --git a/src/systemd/src/basic/fs-util.c b/src/systemd/src/basic/fs-util.c
index da9b670337..049b238e8d 100644
--- a/src/systemd/src/basic/fs-util.c
+++ b/src/systemd/src/basic/fs-util.c
@@ -248,6 +248,21 @@ int fchmod_umask(int fd, mode_t m) {
}
#if 0 /* NM_IGNORED */
+int fchmod_opath(int fd, mode_t m) {
+ char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+
+ /* This function operates also on fd that might have been opened with
+ * O_PATH. Indeed fchmodat() doesn't have the AT_EMPTY_PATH flag like
+ * fchownat() does. */
+
+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+
+ if (chmod(procfs_path, m) < 0)
+ return -errno;
+
+ return 0;
+}
+
int fd_warn_permissions(const char *path, int fd) {
struct stat st;
@@ -911,25 +926,12 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
return exists;
chased_one:
-
if (ret) {
char *c;
- if (done) {
- if (todo) {
- c = strjoin(done, todo);
- if (!c)
- return -ENOMEM;
- } else
- c = TAKE_PTR(done);
- } else {
- if (todo)
- c = strdup(todo);
- else
- c = strdup("/");
- if (!c)
- return -ENOMEM;
- }
+ c = strjoin(strempty(done), todo);
+ if (!c)
+ return -ENOMEM;
*ret = c;
}
diff --git a/src/systemd/src/basic/fs-util.h b/src/systemd/src/basic/fs-util.h
index 2b1d2097fd..6157fe81bf 100644
--- a/src/systemd/src/basic/fs-util.h
+++ b/src/systemd/src/basic/fs-util.h
@@ -33,6 +33,7 @@ int readlink_and_make_absolute(const char *p, char **r);
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
int fchmod_umask(int fd, mode_t mode);
+int fchmod_opath(int fd, mode_t m);
int fd_warn_permissions(const char *path, int fd);
diff --git a/src/systemd/src/basic/hashmap.c b/src/systemd/src/basic/hashmap.c
index c305f1c5fa..b8a8e37b5c 100644
--- a/src/systemd/src/basic/hashmap.c
+++ b/src/systemd/src/basic/hashmap.c
@@ -283,7 +283,7 @@ static const struct hashmap_type_info hashmap_type_info[_HASHMAP_TYPE_MAX] = {
},
};
-#ifdef VALGRIND
+#if VALGRIND
__attribute__((destructor)) static void cleanup_pools(void) {
_cleanup_free_ char *t = NULL;
int r;
diff --git a/src/systemd/src/basic/hexdecoct.c b/src/systemd/src/basic/hexdecoct.c
index 16a35156bf..1fe410f56a 100644
--- a/src/systemd/src/basic/hexdecoct.c
+++ b/src/systemd/src/basic/hexdecoct.c
@@ -79,33 +79,69 @@ char *hexmem(const void *p, size_t l) {
return r;
}
-int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
- _cleanup_free_ uint8_t *r = NULL;
- uint8_t *z;
+static int unhex_next(const char **p, size_t *l) {
+ int r;
+
+ assert(p);
+ assert(l);
+
+ /* Find the next non-whitespace character, and decode it. We
+ * greedily skip all preceeding and all following whitespace. */
+
+ for (;;) {
+ if (*l == 0)
+ return -EPIPE;
+
+ if (!strchr(WHITESPACE, **p))
+ break;
+
+ /* Skip leading whitespace */
+ (*p)++, (*l)--;
+ }
+
+ r = unhexchar(**p);
+ if (r < 0)
+ return r;
+
+ for (;;) {
+ (*p)++, (*l)--;
+
+ if (*l == 0 || !strchr(WHITESPACE, **p))
+ break;
+
+ /* Skip following whitespace */
+ }
+
+ return r;
+}
+
+int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) {
+ _cleanup_free_ uint8_t *buf = NULL;
const char *x;
+ uint8_t *z;
- assert(mem);
- assert(len);
+ assert(ret);
+ assert(ret_len);
assert(p || l == 0);
if (l == (size_t) -1)
l = strlen(p);
- if (l % 2 != 0)
- return -EINVAL;
-
- z = r = malloc((l + 1) / 2 + 1);
- if (!r)
+ /* Note that the calculation of memory size is an upper boundary, as we ignore whitespace while decoding */
+ buf = malloc((l + 1) / 2 + 1);
+ if (!buf)
return -ENOMEM;
- for (x = p; x < p + l; x += 2) {
+ for (x = p, z = buf;;) {
int a, b;
- a = unhexchar(x[0]);
+ a = unhex_next(&x, &l);
+ if (a == -EPIPE) /* End of string */
+ break;
if (a < 0)
return a;
- b = unhexchar(x[1]);
+ b = unhex_next(&x, &l);
if (b < 0)
return b;
@@ -114,8 +150,8 @@ int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
*z = 0;
- *mem = TAKE_PTR(r);
- *len = (l + 1) / 2;
+ *ret_len = (size_t) (z - buf);
+ *ret = TAKE_PTR(buf);
return 0;
}
@@ -184,7 +220,7 @@ char *base32hexmem(const void *p, size_t l, bool padding) {
for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) {
/* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
- x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
+ * x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
*(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
*(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
*(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
@@ -284,7 +320,7 @@ int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_l
}
/* a group of eight input bytes needs five output bytes, in case of
- padding we need to add some extra bytes */
+ * padding we need to add some extra bytes */
len = (l / 8) * 5;
switch (l % 8) {
@@ -312,7 +348,7 @@ int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_l
for (x = p; x < p + (l / 8) * 8; x += 8) {
/* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW
- e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
+ * e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
a = unbase32hexchar(x[0]);
if (a < 0)
return -EINVAL;
@@ -668,7 +704,7 @@ int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) {
l = strlen(p);
/* A group of four input bytes needs three output bytes, in case of padding we need to add two or three extra
- bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */
+ * bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */
len = (l / 4) * 3 + (l % 4 != 0 ? (l % 4) - 1 : 0);
buf = malloc(len + 1);
@@ -736,9 +772,7 @@ int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) {
*z = 0;
- if (ret_size)
- *ret_size = (size_t) (z - buf);
-
+ *ret_size = (size_t) (z - buf);
*ret = TAKE_PTR(buf);
return 0;
diff --git a/src/systemd/src/basic/io-util.h b/src/systemd/src/basic/io-util.h
index c34d97c653..e4717b6f30 100644
--- a/src/systemd/src/basic/io-util.h
+++ b/src/systemd/src/basic/io-util.h
@@ -28,9 +28,8 @@ int fd_wait_for_event(int fd, int event, usec_t timeout);
ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length);
-static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) {
- unsigned j;
- size_t r = 0;
+static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, size_t n) {
+ size_t j, r = 0;
for (j = 0; j < n; j++)
r += i[j].iov_len;
@@ -38,8 +37,8 @@ static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) {
return r;
}
-static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) {
- unsigned j;
+static inline size_t IOVEC_INCREMENT(struct iovec *i, size_t n, size_t k) {
+ size_t j;
for (j = 0; j < n; j++) {
size_t sub;
diff --git a/src/systemd/src/basic/mempool.c b/src/systemd/src/basic/mempool.c
index 16aca7a3e6..0709676696 100644
--- a/src/systemd/src/basic/mempool.c
+++ b/src/systemd/src/basic/mempool.c
@@ -17,12 +17,12 @@
struct pool {
struct pool *next;
- unsigned n_tiles;
- unsigned n_used;
+ size_t n_tiles;
+ size_t n_used;
};
void* mempool_alloc_tile(struct mempool *mp) {
- unsigned i;
+ size_t i;
/* When a tile is released we add it to the list and simply
* place the next pointer at its offset 0. */
@@ -40,8 +40,7 @@ void* mempool_alloc_tile(struct mempool *mp) {
if (_unlikely_(!mp->first_pool) ||
_unlikely_(mp->first_pool->n_used >= mp->first_pool->n_tiles)) {
- unsigned n;
- size_t size;
+ size_t size, n;
struct pool *p;
n = mp->first_pool ? mp->first_pool->n_tiles : 0;
@@ -79,7 +78,7 @@ void mempool_free_tile(struct mempool *mp, void *p) {
mp->freelist = p;
}
-#ifdef VALGRIND
+#if VALGRIND
void mempool_drop(struct mempool *mp) {
struct pool *p = mp->first_pool;
diff --git a/src/systemd/src/basic/mempool.h b/src/systemd/src/basic/mempool.h
index 5322fd480d..68249cd881 100644
--- a/src/systemd/src/basic/mempool.h
+++ b/src/systemd/src/basic/mempool.h
@@ -30,6 +30,6 @@ static struct mempool pool_name = { \
}
-#ifdef VALGRIND
+#if VALGRIND
void mempool_drop(struct mempool *mp);
#endif
diff --git a/src/systemd/src/basic/parse-util.c b/src/systemd/src/basic/parse-util.c
index b2d3689e1e..ae43a0411b 100644
--- a/src/systemd/src/basic/parse-util.c
+++ b/src/systemd/src/basic/parse-util.c
@@ -13,12 +13,14 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/socket.h>
#include "alloc-util.h"
#include "errno-list.h"
#include "extract-word.h"
#include "locale-util.h"
#include "macro.h"
+#include "missing.h"
#include "parse-util.h"
#include "process-util.h"
#include "string-util.h"
@@ -96,6 +98,30 @@ int parse_ifindex(const char *s, int *ret) {
return 0;
}
+int parse_mtu(int family, const char *s, uint32_t *ret) {
+ uint64_t u;
+ size_t m;
+ int r;
+
+ r = parse_size(s, 1024, &u);
+ if (r < 0)
+ return r;
+
+ if (u > UINT32_MAX)
+ return -ERANGE;
+
+ if (family == AF_INET6)
+ m = IPV6_MIN_MTU; /* This is 1280 */
+ else
+ m = IPV4_MIN_MTU; /* For all other protocols, including 'unspecified' we assume the IPv4 minimal MTU */
+
+ if (u < m)
+ return -ERANGE;
+
+ *ret = (uint32_t) u;
+ return 0;
+}
+
int parse_size(const char *t, uint64_t base, uint64_t *size) {
/* Soo, sometimes we want to parse IEC binary suffixes, and
@@ -655,4 +681,21 @@ int parse_dev(const char *s, dev_t *ret) {
*ret = d;
return 0;
}
+
+int parse_oom_score_adjust(const char *s, int *ret) {
+ int r, v;
+
+ assert(s);
+ assert(ret);
+
+ r = safe_atoi(s, &v);
+ if (r < 0)
+ return r;
+
+ if (v < OOM_SCORE_ADJ_MIN || v > OOM_SCORE_ADJ_MAX)
+ return -ERANGE;
+
+ *ret = v;
+ return 0;
+}
#endif /* NM_IGNORED */
diff --git a/src/systemd/src/basic/parse-util.h b/src/systemd/src/basic/parse-util.h
index 74c30b5570..2b75b938c7 100644
--- a/src/systemd/src/basic/parse-util.h
+++ b/src/systemd/src/basic/parse-util.h
@@ -22,6 +22,7 @@ int parse_dev(const char *s, dev_t *ret);
int parse_pid(const char *s, pid_t* ret_pid);
int parse_mode(const char *s, mode_t *ret);
int parse_ifindex(const char *s, int *ret);
+int parse_mtu(int family, const char *s, uint32_t *ret);
int parse_size(const char *t, uint64_t base, uint64_t *size);
int parse_range(const char *t, unsigned *lower, unsigned *upper);
@@ -117,3 +118,5 @@ int parse_percent(const char *p);
int parse_nice(const char *p, int *ret);
int parse_ip_port(const char *s, uint16_t *ret);
+
+int parse_oom_score_adjust(const char *s, int *ret);
diff --git a/src/systemd/src/basic/path-util.c b/src/systemd/src/basic/path-util.c
index 32fbfbb490..567fc61cea 100644
--- a/src/systemd/src/basic/path-util.c
+++ b/src/systemd/src/basic/path-util.c
@@ -690,11 +690,12 @@ int parse_path_argument_and_warn(const char *path, bool suppress_root, char **ar
return log_error_errno(r, "Failed to parse path \"%s\" and make it absolute: %m", path);
path_kill_slashes(p);
- if (suppress_root && path_equal(p, "/"))
+ if (suppress_root && empty_or_root(p))
p = mfree(p);
free(*arg);
*arg = p;
+
return 0;
}
diff --git a/src/systemd/src/basic/path-util.h b/src/systemd/src/basic/path-util.h
index a1829c41b1..79db819e4d 100644
--- a/src/systemd/src/basic/path-util.h
+++ b/src/systemd/src/basic/path-util.h
@@ -166,3 +166,6 @@ static inline const char *skip_dev_prefix(const char *p) {
}
bool empty_or_root(const char *root);
+static inline const char *empty_to_root(const char *path) {
+ return isempty(path) ? "/" : path;
+}
diff --git a/src/systemd/src/basic/process-util.c b/src/systemd/src/basic/process-util.c
index 80bf4d435e..4af99957d2 100644
--- a/src/systemd/src/basic/process-util.c
+++ b/src/systemd/src/basic/process-util.c
@@ -885,7 +885,7 @@ int getenv_for_pid(pid_t pid, const char *field, char **ret) {
do {
char line[LINE_MAX];
- unsigned i;
+ size_t i;
for (i = 0; i < sizeof(line)-1; i++) {
int c;
@@ -1384,9 +1384,9 @@ int safe_fork_full(
return 0;
}
-int fork_agent(const char *name, const int except[], unsigned n_except, pid_t *ret_pid, const char *path, ...) {
+int fork_agent(const char *name, const int except[], size_t n_except, pid_t *ret_pid, const char *path, ...) {
bool stdout_is_tty, stderr_is_tty;
- unsigned n, i;
+ size_t n, i;
va_list ap;
char **l;
int r;
@@ -1442,7 +1442,7 @@ int fork_agent(const char *name, const int except[], unsigned n_except, pid_t *r
va_end(ap);
/* Allocate strv */
- l = alloca(sizeof(char *) * (n + 1));
+ l = newa(char*, n + 1);
/* Fill in arguments */
va_start(ap, path);
@@ -1454,6 +1454,15 @@ int fork_agent(const char *name, const int except[], unsigned n_except, pid_t *r
_exit(EXIT_FAILURE);
}
+int set_oom_score_adjust(int value) {
+ char t[DECIMAL_STR_MAX(int)];
+
+ sprintf(t, "%i", value);
+
+ return write_string_file("/proc/self/oom_score_adj", t,
+ WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_DISABLE_BUFFER);
+}
+
static const char *const ioprio_class_table[] = {
[IOPRIO_CLASS_NONE] = "none",
[IOPRIO_CLASS_RT] = "realtime",
diff --git a/src/systemd/src/basic/process-util.h b/src/systemd/src/basic/process-util.h
index 3641e6e8d0..e3bf36bf04 100644
--- a/src/systemd/src/basic/process-util.h
+++ b/src/systemd/src/basic/process-util.h
@@ -173,7 +173,9 @@ static inline int safe_fork(const char *name, ForkFlags flags, pid_t *ret_pid) {
return safe_fork_full(name, NULL, 0, flags, ret_pid);
}
-int fork_agent(const char *name, const int except[], unsigned n_except, pid_t *pid, const char *path, ...);
+int fork_agent(const char *name, const int except[], size_t n_except, pid_t *pid, const char *path, ...);
+
+int set_oom_score_adjust(int value);
#if SIZEOF_PID_T == 4
/* The highest possibly (theoretic) pid_t value on this architecture. */
diff --git a/src/systemd/src/basic/random-util.c b/src/systemd/src/basic/random-util.c
index 9447d6b32a..d80751cfe9 100644
--- a/src/systemd/src/basic/random-util.c
+++ b/src/systemd/src/basic/random-util.c
@@ -37,7 +37,7 @@ int acquire_random_bytes(void *p, size_t n, bool high_quality_required) {
static int have_syscall = -1;
_cleanup_close_ int fd = -1;
- unsigned already_done = 0;
+ size_t already_done = 0;
int r;
/* Gathers some randomness from the kernel. This call will never block. If
diff --git a/src/systemd/src/basic/set.h b/src/systemd/src/basic/set.h
index 6f937af929..dc0f1e17e6 100644
--- a/src/systemd/src/basic/set.h
+++ b/src/systemd/src/basic/set.h
@@ -136,5 +136,3 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free);
#define _cleanup_set_free_ _cleanup_(set_freep)
#define _cleanup_set_free_free_ _cleanup_(set_free_freep)
-
-int set_make(Set **ret, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS, void *add, ...);
diff --git a/src/systemd/src/basic/signal-util.h b/src/systemd/src/basic/signal-util.h
index de2364fac4..0c43467b63 100644
--- a/src/systemd/src/basic/signal-util.h
+++ b/src/systemd/src/basic/signal-util.h
@@ -24,8 +24,6 @@ int sigprocmask_many(int how, sigset_t *old, ...);
const char *signal_to_string(int i) _const_;
int signal_from_string(const char *s) _pure_;
-int signal_from_string_try_harder(const char *s);
-
void nop_signal_handler(int sig);
static inline void block_signals_reset(sigset_t *ss) {
diff --git a/src/systemd/src/basic/stat-util.c b/src/systemd/src/basic/stat-util.c
new file mode 100644
index 0000000000..28e75618bc
--- /dev/null
+++ b/src/systemd/src/basic/stat-util.c
@@ -0,0 +1,292 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/***
+ This file is part of systemd.
+
+ Copyright 2010-2012 Lennart Poettering
+***/
+
+#include "nm-sd-adapt.h"
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/magic.h>
+#include <sched.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "dirent-util.h"
+#include "fd-util.h"
+#include "fs-util.h"
+#include "macro.h"
+#include "missing.h"
+#include "stat-util.h"
+#include "string-util.h"
+
+#if 0 /* NM_IGNORED */
+int is_symlink(const char *path) {
+ struct stat info;
+
+ assert(path);
+
+ if (lstat(path, &info) < 0)
+ return -errno;
+
+ return !!S_ISLNK(info.st_mode);
+}
+
+int is_dir(const char* path, bool follow) {
+ struct stat st;
+ int r;
+
+ assert(path);
+
+ if (follow)
+ r = stat(path, &st);
+ else
+ r = lstat(path, &st);
+ if (r < 0)
+ return -errno;
+
+ return !!S_ISDIR(st.st_mode);
+}
+
+int is_device_node(const char *path) {
+ struct stat info;
+
+ assert(path);
+
+ if (lstat(path, &info) < 0)
+ return -errno;
+
+ return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode));
+}
+
+int dir_is_empty(const char *path) {
+ _cleanup_closedir_ DIR *d;
+ struct dirent *de;
+
+ d = opendir(path);
+ if (!d)
+ return -errno;
+
+ FOREACH_DIRENT(de, d, return -errno)
+ return 0;
+
+ return 1;
+}
+
+bool null_or_empty(struct stat *st) {
+ assert(st);
+
+ if (S_ISREG(st->st_mode) && st->st_size <= 0)
+ return true;
+
+ /* We don't want to hardcode the major/minor of /dev/null,
+ * hence we do a simpler "is this a device node?" check. */
+
+ if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
+ return true;
+
+ return false;
+}
+
+int null_or_empty_path(const char *fn) {
+ struct stat st;
+
+ assert(fn);
+
+ if (stat(fn, &st) < 0)
+ return -errno;
+
+ return null_or_empty(&st);
+}
+
+int null_or_empty_fd(int fd) {
+ struct stat st;
+
+ assert(fd >= 0);
+
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
+ return null_or_empty(&st);
+}
+
+int path_is_read_only_fs(const char *path) {
+ struct statvfs st;
+
+ assert(path);
+
+ if (statvfs(path, &st) < 0)
+ return -errno;
+
+ if (st.f_flag & ST_RDONLY)
+ return true;
+
+ /* On NFS, statvfs() might not reflect whether we can actually
+ * write to the remote share. Let's try again with
+ * access(W_OK) which is more reliable, at least sometimes. */
+ if (access(path, W_OK) < 0 && errno == EROFS)
+ return true;
+
+ return false;
+}
+
+int path_is_os_tree(const char *path) {
+ int r;
+
+ assert(path);
+
+ /* Does the path exist at all? If not, generate an error immediately. This is useful so that a missing root dir
+ * always results in -ENOENT, and we can properly distuingish the case where the whole root doesn't exist from
+ * the case where just the os-release file is missing. */
+ if (laccess(path, F_OK) < 0)
+ return -errno;
+
+ /* We use /usr/lib/os-release as flag file if something is an OS */
+ r = chase_symlinks("/usr/lib/os-release", path, CHASE_PREFIX_ROOT, NULL);
+ if (r == -ENOENT) {
+
+ /* Also check for the old location in /etc, just in case. */
+ r = chase_symlinks("/etc/os-release", path, CHASE_PREFIX_ROOT, NULL);
+ if (r == -ENOENT)
+ return 0; /* We got nothing */
+ }
+ if (r < 0)
+ return r;
+
+ return 1;
+}
+
+int files_same(const char *filea, const char *fileb, int flags) {
+ struct stat a, b;
+
+ assert(filea);
+ assert(fileb);
+
+ if (fstatat(AT_FDCWD, filea, &a, flags) < 0)
+ return -errno;
+
+ if (fstatat(AT_FDCWD, fileb, &b, flags) < 0)
+ return -errno;
+
+ return a.st_dev == b.st_dev &&
+ a.st_ino == b.st_ino;
+}
+
+bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) {
+ assert(s);
+ assert_cc(sizeof(statfs_f_type_t) >= sizeof(s->f_type));
+
+ return F_TYPE_EQUAL(s->f_type, magic_value);
+}
+
+int fd_is_fs_type(int fd, statfs_f_type_t magic_value) {
+ struct statfs s;
+
+ if (fstatfs(fd, &s) < 0)
+ return -errno;
+
+ return is_fs_type(&s, magic_value);
+}
+
+int path_is_fs_type(const char *path, statfs_f_type_t magic_value) {
+ _cleanup_close_ int fd = -1;
+
+ fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH);
+ if (fd < 0)
+ return -errno;
+
+ return fd_is_fs_type(fd, magic_value);
+}
+
+bool is_temporary_fs(const struct statfs *s) {
+ return is_fs_type(s, TMPFS_MAGIC) ||
+ is_fs_type(s, RAMFS_MAGIC);
+}
+
+bool is_network_fs(const struct statfs *s) {
+ return is_fs_type(s, CIFS_MAGIC_NUMBER) ||
+ is_fs_type(s, CODA_SUPER_MAGIC) ||
+ is_fs_type(s, NCP_SUPER_MAGIC) ||
+ is_fs_type(s, NFS_SUPER_MAGIC) ||
+ is_fs_type(s, SMB_SUPER_MAGIC) ||
+ is_fs_type(s, V9FS_MAGIC) ||
+ is_fs_type(s, AFS_SUPER_MAGIC) ||
+ is_fs_type(s, OCFS2_SUPER_MAGIC);
+}
+
+int fd_is_temporary_fs(int fd) {
+ struct statfs s;
+
+ if (fstatfs(fd, &s) < 0)
+ return -errno;
+
+ return is_temporary_fs(&s);
+}
+
+int fd_is_network_fs(int fd) {
+ struct statfs s;
+
+ if (fstatfs(fd, &s) < 0)
+ return -errno;
+
+ return is_network_fs(&s);
+}
+
+int fd_is_network_ns(int fd) {
+ int r;
+
+ r = fd_is_fs_type(fd, NSFS_MAGIC);
+ if (r <= 0)
+ return r;
+
+ r = ioctl(fd, NS_GET_NSTYPE);
+ if (r < 0)
+ return -errno;
+
+ return r == CLONE_NEWNET;
+}
+
+int path_is_temporary_fs(const char *path) {
+ _cleanup_close_ int fd = -1;
+
+ fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH);
+ if (fd < 0)
+ return -errno;
+
+ return fd_is_temporary_fs(fd);
+}
+#endif /* NM_IGNORED */
+
+int stat_verify_regular(const struct stat *st) {
+ assert(st);
+
+ /* Checks whether the specified stat() structure refers to a regular file. If not returns an appropriate error
+ * code. */
+
+ if (S_ISDIR(st->st_mode))
+ return -EISDIR;
+
+ if (S_ISLNK(st->st_mode))
+ return -ELOOP;
+
+ if (!S_ISREG(st->st_mode))
+ return -EBADFD;
+
+ return 0;
+}
+
+int fd_verify_regular(int fd) {
+ struct stat st;
+
+ assert(fd >= 0);
+
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
+ return stat_verify_regular(&st);
+}
diff --git a/src/systemd/src/basic/stat-util.h b/src/systemd/src/basic/stat-util.h
new file mode 100644
index 0000000000..d1e8d33001
--- /dev/null
+++ b/src/systemd/src/basic/stat-util.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010-2012 Lennart Poettering
+***/
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <sys/types.h>
+#include <sys/vfs.h>
+
+#include "macro.h"
+
+int is_symlink(const char *path);
+int is_dir(const char *path, bool follow);
+int is_device_node(const char *path);
+
+int dir_is_empty(const char *path);
+
+static inline int dir_is_populated(const char *path) {
+ int r;
+ r = dir_is_empty(path);
+ if (r < 0)
+ return r;
+ return !r;
+}
+
+bool null_or_empty(struct stat *st) _pure_;
+int null_or_empty_path(const char *fn);
+int null_or_empty_fd(int fd);
+
+int path_is_read_only_fs(const char *path);
+int path_is_os_tree(const char *path);
+
+int files_same(const char *filea, const char *fileb, int flags);
+
+/* The .f_type field of struct statfs is really weird defined on
+ * different archs. Let's give its type a name. */
+typedef typeof(((struct statfs*)NULL)->f_type) statfs_f_type_t;
+
+bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) _pure_;
+int fd_is_fs_type(int fd, statfs_f_type_t magic_value);
+int path_is_fs_type(const char *path, statfs_f_type_t magic_value);
+
+bool is_temporary_fs(const struct statfs *s) _pure_;
+bool is_network_fs(const struct statfs *s) _pure_;
+
+int fd_is_temporary_fs(int fd);
+int fd_is_network_fs(int fd);
+
+int fd_is_network_ns(int fd);
+
+int path_is_temporary_fs(const char *path);
+
+/* Because statfs.t_type can be int on some architectures, we have to cast
+ * the const magic to the type, otherwise the compiler warns about
+ * signed/unsigned comparison, because the magic can be 32 bit unsigned.
+ */
+#define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b)
+
+int stat_verify_regular(const struct stat *st);
+int fd_verify_regular(int fd);
diff --git a/src/systemd/src/basic/string-util.c b/src/systemd/src/basic/string-util.c
index a7b3f09620..a60c7dccfe 100644
--- a/src/systemd/src/basic/string-util.c
+++ b/src/systemd/src/basic/string-util.c
@@ -23,6 +23,7 @@
#include "terminal-util.h"
#include "utf8.h"
#include "util.h"
+#include "fileio.h"
int strcmp_ptr(const char *a, const char *b) {
@@ -700,7 +701,8 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
enum {
STATE_OTHER,
STATE_ESCAPE,
- STATE_BRACKET
+ STATE_CSI,
+ STATE_CSO,
} state = STATE_OTHER;
char *obuf = NULL;
size_t osz = 0, isz, shift[2] = {};
@@ -709,7 +711,17 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
assert(ibuf);
assert(*ibuf);
- /* Strips ANSI color and replaces TABs by 8 spaces */
+ /* This does three things:
+ *
+ * 1. Replaces TABs by 8 spaces
+ * 2. Strips ANSI color sequences (a subset of CSI), i.e. ESC '[' … 'm' sequences
+ * 3. Strips ANSI operating system sequences (CSO), i.e. ESC ']' … BEL sequences
+ *
+ * Everything else will be left as it is. In particular other ANSI sequences are left as they are, as are any
+ * other special characters. Truncated ANSI sequences are left-as is too. This call is supposed to suppress the
+ * most basic formatting noise, but nothing else.
+ *
+ * Why care for CSO sequences? Well, to undo what terminal_urlify() and friends generate. */
isz = _isz ? *_isz : strlen(*ibuf);
@@ -744,8 +756,11 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
fputc('\x1B', f);
advance_offsets(i - *ibuf, highlight, shift, 1);
break;
- } else if (*i == '[') {
- state = STATE_BRACKET;
+ } else if (*i == '[') { /* ANSI CSI */
+ state = STATE_CSI;
+ begin = i + 1;
+ } else if (*i == ']') { /* ANSI CSO */
+ state = STATE_CSO;
begin = i + 1;
} else {
fputc('\x1B', f);
@@ -756,10 +771,10 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
break;
- case STATE_BRACKET:
+ case STATE_CSI:
- if (i >= *ibuf + isz || /* EOT */
- (!(*i >= '0' && *i <= '9') && !IN_SET(*i, ';', 'm'))) {
+ if (i >= *ibuf + isz || /* EOT … */
+ !strchr("01234567890;m", *i)) { /* … or invalid chars in sequence */
fputc('\x1B', f);
fputc('[', f);
advance_offsets(i - *ibuf, highlight, shift, 2);
@@ -767,11 +782,26 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
i = begin-1;
} else if (*i == 'm')
state = STATE_OTHER;
+
+ break;
+
+ case STATE_CSO:
+
+ if (i >= *ibuf + isz || /* EOT … */
+ (*i != '\a' && (uint8_t) *i < 32U) || (uint8_t) *i > 126U) { /* … or invalid chars in sequence */
+ fputc('\x1B', f);
+ fputc(']', f);
+ advance_offsets(i - *ibuf, highlight, shift, 2);
+ state = STATE_OTHER;
+ i = begin-1;
+ } else if (*i == '\a')
+ state = STATE_OTHER;
+
break;
}
}
- if (ferror(f)) {
+ if (fflush_and_check(f) < 0) {
fclose(f);
return mfree(obuf);
}
diff --git a/src/systemd/src/basic/string-util.h b/src/systemd/src/basic/string-util.h
index 4f500c87d4..5a10eeabfe 100644
--- a/src/systemd/src/basic/string-util.h
+++ b/src/systemd/src/basic/string-util.h
@@ -58,7 +58,7 @@ static inline const char *empty_to_null(const char *p) {
return isempty(p) ? NULL : p;
}
-static inline const char *strdash_if_empty(const char *str) {
+static inline const char *empty_to_dash(const char *str) {
return isempty(str) ? "-" : str;
}
@@ -109,7 +109,7 @@ char *strjoin_real(const char *x, ...) _sentinel_;
const char *_appendees_[] = { a, __VA_ARGS__ }; \
char *_d_, *_p_; \
size_t _len_ = 0; \
- unsigned _i_; \
+ size_t _i_; \
for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \
_len_ += strlen(_appendees_[_i_]); \
_p_ = _d_ = alloca(_len_ + 1); \
diff --git a/src/systemd/src/basic/strv.c b/src/systemd/src/basic/strv.c
index 5bde3826fc..9d5000aac1 100644
--- a/src/systemd/src/basic/strv.c
+++ b/src/systemd/src/basic/strv.c
@@ -109,8 +109,8 @@ char **strv_copy(char * const *l) {
return r;
}
-unsigned strv_length(char * const *l) {
- unsigned n = 0;
+size_t strv_length(char * const *l) {
+ size_t n = 0;
if (!l)
return 0;
@@ -123,8 +123,8 @@ unsigned strv_length(char * const *l) {
char **strv_new_ap(const char *x, va_list ap) {
const char *s;
- char **a;
- unsigned n = 0, i = 0;
+ _cleanup_strv_free_ char **a = NULL;
+ size_t n = 0, i = 0;
va_list aq;
/* As a special trick we ignore all listed strings that equal
@@ -154,7 +154,7 @@ char **strv_new_ap(const char *x, va_list ap) {
if (x != STRV_IGNORE) {
a[i] = strdup(x);
if (!a[i])
- goto fail;
+ return NULL;
i++;
}
@@ -165,7 +165,7 @@ char **strv_new_ap(const char *x, va_list ap) {
a[i] = strdup(s);
if (!a[i])
- goto fail;
+ return NULL;
i++;
}
@@ -173,11 +173,7 @@ char **strv_new_ap(const char *x, va_list ap) {
a[i] = NULL;
- return a;
-
-fail:
- strv_free(a);
- return NULL;
+ return TAKE_PTR(a);
}
char **strv_new(const char *x, ...) {
@@ -259,7 +255,7 @@ int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
char **strv_split(const char *s, const char *separator) {
const char *word, *state;
size_t l;
- unsigned n, i;
+ size_t n, i;
char **r;
assert(s);
@@ -289,7 +285,7 @@ char **strv_split(const char *s, const char *separator) {
char **strv_split_newlines(const char *s) {
char **l;
- unsigned n;
+ size_t n;
assert(s);
@@ -384,7 +380,7 @@ char *strv_join(char **l, const char *separator) {
int strv_push(char ***l, char *value) {
char **c;
- unsigned n, m;
+ size_t n, m;
if (!value)
return 0;
@@ -409,7 +405,7 @@ int strv_push(char ***l, char *value) {
int strv_push_pair(char ***l, char *a, char *b) {
char **c;
- unsigned n, m;
+ size_t n, m;
if (!a && !b)
return 0;
@@ -435,9 +431,9 @@ int strv_push_pair(char ***l, char *a, char *b) {
return 0;
}
-int strv_insert(char ***l, unsigned position, char *value) {
+int strv_insert(char ***l, size_t position, char *value) {
char **c;
- unsigned n, m, i;
+ size_t n, m, i;
if (!value)
return 0;
@@ -605,7 +601,7 @@ char **strv_parse_nulstr(const char *s, size_t l) {
*/
const char *p;
- unsigned c = 0, i = 0;
+ size_t c = 0, i = 0;
char **v;
assert(s || l <= 0);
@@ -769,7 +765,7 @@ int strv_extendf(char ***l, const char *format, ...) {
}
char **strv_reverse(char **l) {
- unsigned n, i;
+ size_t n, i;
n = strv_length(l);
if (n <= 1)
diff --git a/src/systemd/src/basic/strv.h b/src/systemd/src/basic/strv.h
index 79512c0ce3..958c5f3a98 100644
--- a/src/systemd/src/basic/strv.h
+++ b/src/systemd/src/basic/strv.h
@@ -32,7 +32,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(char**, strv_free_erase);
void strv_clear(char **l);
char **strv_copy(char * const *l);
-unsigned strv_length(char * const *l) _pure_;
+size_t strv_length(char * const *l) _pure_;
int strv_extend_strv(char ***a, char **b, bool filter_duplicates);
int strv_extend_strv_concat(char ***a, char **b, const char *suffix);
@@ -41,7 +41,7 @@ int strv_extendf(char ***l, const char *format, ...) _printf_(2,0);
int strv_extend_front(char ***l, const char *value);
int strv_push(char ***l, char *value);
int strv_push_pair(char ***l, char *a, char *b);
-int strv_insert(char ***l, unsigned position, char *value);
+int strv_insert(char ***l, size_t position, char *value);
static inline int strv_push_prepend(char ***l, char *value) {
return strv_insert(l, 0, value);
@@ -113,7 +113,7 @@ void strv_print(char **l);
if (!first) \
_l = (char**) &first; \
else { \
- unsigned _n; \
+ size_t _n; \
va_list _ap; \
\
_n = 1; \
diff --git a/src/systemd/src/basic/time-util.c b/src/systemd/src/basic/time-util.c
index 962d3dceeb..fa9f66f2ae 100644
--- a/src/systemd/src/basic/time-util.c
+++ b/src/systemd/src/basic/time-util.c
@@ -23,11 +23,13 @@
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
+#include "io-util.h"
#include "log.h"
#include "macro.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
+#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
@@ -438,7 +440,7 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
{ "us", 1 },
};
- unsigned i;
+ size_t i;
char *p = buf;
bool something = false;
@@ -617,10 +619,9 @@ static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
time_t x;
usec_t x_usec, plus = 0, minus = 0, ret;
int r, weekday = -1, dst = -1;
- unsigned i;
+ size_t i;
- /*
- * Allowed syntaxes:
+ /* Allowed syntaxes:
*
* 2012-09-22 16:34:22
* 2012-09-22 16:34 (seconds will be set to 0)
@@ -634,7 +635,6 @@ static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
* +5min
* -5days
* @2147483647 (seconds since epoch)
- *
*/
assert(t);
@@ -693,10 +693,10 @@ static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
tzset();
/* See if the timestamp is suffixed by either the DST or non-DST local timezone. Note that we only
- * support the local timezones here, nothing else. Not because we wouldn't want to, but simply because
- * there are no nice APIs available to cover this. By accepting the local time zone strings, we make
- * sure that all timestamps written by format_timestamp() can be parsed correctly, even though we don't
- * support arbitrary timezone specifications. */
+ * support the local timezones here, nothing else. Not because we wouldn't want to, but simply because
+ * there are no nice APIs available to cover this. By accepting the local time zone strings, we make
+ * sure that all timestamps written by format_timestamp() can be parsed correctly, even though we don't
+ * support arbitrary timezone specifications. */
for (j = 0; j <= 1; j++) {
@@ -882,7 +882,7 @@ int parse_timestamp(const char *t, usec_t *usec) {
int r;
last_space = strrchr(t, ' ');
- if (last_space != NULL && timezone_is_valid(last_space + 1))
+ if (last_space != NULL && timezone_is_valid(last_space + 1, LOG_DEBUG))
tz = last_space + 1;
if (!tz || endswith_no_case(t, " UTC"))
@@ -908,10 +908,10 @@ int parse_timestamp(const char *t, usec_t *usec) {
tzset();
/* If there is a timezone that matches the tzname fields, leave the parsing to the implementation.
- * Otherwise just cut it off */
+ * Otherwise just cut it off. */
with_tz = !STR_IN_SET(tz, tzname[0], tzname[1]);
- /*cut off the timezone if we dont need it*/
+ /* Cut off the timezone if we dont need it. */
if (with_tz)
t = strndupa(t, last_space - t);
@@ -965,7 +965,7 @@ static char* extract_multiplier(char *p, usec_t *multiplier) {
{ "us", 1ULL },
{ "µs", 1ULL },
};
- unsigned i;
+ size_t i;
for (i = 0; i < ELEMENTSOF(table); i++) {
char *e;
@@ -1139,8 +1139,8 @@ int parse_nsec(const char *t, nsec_t *nsec) {
for (;;) {
long long l, z = 0;
+ size_t n = 0, i;
char *e;
- unsigned i, n = 0;
p += strspn(p, WHITESPACE);
@@ -1281,10 +1281,12 @@ int get_timezones(char ***ret) {
}
#endif /* NM_IGNORED */
-bool timezone_is_valid(const char *name) {
+bool timezone_is_valid(const char *name, int log_level) {
bool slash = false;
const char *p, *t;
- struct stat st;
+ _cleanup_close_ int fd = -1;
+ char buf[4];
+ int r;
if (isempty(name))
return false;
@@ -1313,11 +1315,30 @@ bool timezone_is_valid(const char *name) {
return false;
t = strjoina("/usr/share/zoneinfo/", name);
- if (stat(t, &st) < 0)
+
+ fd = open(t, O_RDONLY|O_CLOEXEC);
+ if (fd < 0) {
+ log_full_errno(log_level, errno, "Failed to open timezone file '%s': %m", t);
return false;
+ }
- if (!S_ISREG(st.st_mode))
+ r = fd_verify_regular(fd);
+ if (r < 0) {
+ log_full_errno(log_level, r, "Timezone file '%s' is not a regular file: %m", t);
return false;
+ }
+
+ r = loop_read_exact(fd, buf, 4, false);
+ if (r < 0) {
+ log_full_errno(log_level, r, "Failed to read from timezone file '%s': %m", t);
+ return false;
+ }
+
+ /* Magic from tzfile(5) */
+ if (memcmp(buf, "TZif", 4) != 0) {
+ log_full(log_level, "Timezone file '%s' has wrong magic bytes", t);
+ return false;
+ }
return true;
}
@@ -1389,7 +1410,7 @@ int get_timezone(char **tz) {
if (!e)
return -EINVAL;
- if (!timezone_is_valid(e))
+ if (!timezone_is_valid(e, LOG_DEBUG))
return -EINVAL;
z = strdup(e);
diff --git a/src/systemd/src/basic/time-util.h b/src/systemd/src/basic/time-util.h
index 5b2674a4b6..e720688c2b 100644
--- a/src/systemd/src/basic/time-util.h
+++ b/src/systemd/src/basic/time-util.h
@@ -128,7 +128,7 @@ int parse_nsec(const char *t, nsec_t *nsec);
bool ntp_synced(void);
int get_timezones(char ***l);
-bool timezone_is_valid(const char *name);
+bool timezone_is_valid(const char *name, int log_level);
bool clock_boottime_supported(void);
bool clock_supported(clockid_t clock);
diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.c b/src/systemd/src/libsystemd-network/dhcp-identifier.c
index 746eba006d..6f8adfa610 100644
--- a/src/systemd/src/libsystemd-network/dhcp-identifier.c
+++ b/src/systemd/src/libsystemd-network/dhcp-identifier.c
@@ -86,7 +86,7 @@ int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_i
#if 0 /* NM_IGNORED */
/* name is a pointer to memory in the udev_device struct, so must
have the same scope */
- _cleanup_udev_device_unref_ struct udev_device *device = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *device = NULL;
#else /* NM_IGNORED */
char name_buf[IF_NAMESIZE];
#endif /* NM_IGNORED */
@@ -96,7 +96,7 @@ int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_i
#if 0 /* NM_IGNORED */
if (detect_container() <= 0) {
/* not in a container, udev will be around */
- _cleanup_udev_unref_ struct udev *udev;
+ _cleanup_(udev_unrefp) struct udev *udev;
char ifindex_str[2 + DECIMAL_STR_MAX(int)];
udev = udev_new();
diff --git a/src/systemd/src/libsystemd-network/dhcp-option.c b/src/systemd/src/libsystemd-network/dhcp-option.c
index 4e39665e70..86e67358c3 100644
--- a/src/systemd/src/libsystemd-network/dhcp-option.c
+++ b/src/systemd/src/libsystemd-network/dhcp-option.c
@@ -14,6 +14,7 @@
#include "alloc-util.h"
#include "utf8.h"
+#include "strv.h"
#include "dhcp-internal.h"
@@ -37,6 +38,34 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
*offset += 1;
break;
+ case SD_DHCP_OPTION_USER_CLASS: {
+ size_t len = 0;
+ 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) {
+ len = strlen(*s);
+
+ if (len > 255)
+ return -ENAMETOOLONG;
+
+ options[*offset] = len;
+
+ memcpy_safe(&options[*offset + 1], *s, len);
+ *offset += len + 1;
+ }
+
+ break;
+ }
default:
if (size < *offset + optlen + 2)
return -ENOBUFS;
diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c
index f23318cb9a..e05f52d454 100644
--- a/src/systemd/src/libsystemd-network/network-internal.c
+++ b/src/systemd/src/libsystemd-network/network-internal.c
@@ -86,7 +86,7 @@ static bool net_condition_test_strv(char * const *raw_patterns,
/* If the patterns begin with "!", edit it out and negate the test. */
if (raw_patterns[0][0] == '!') {
char **patterns;
- unsigned i, length;
+ size_t i, length;
length = strv_length(raw_patterns) + 1; /* Include the NULL. */
patterns = newa(char*, length);
@@ -100,7 +100,7 @@ static bool net_condition_test_strv(char * const *raw_patterns,
return string && strv_fnmatch(raw_patterns, string, 0);
}
-bool net_match_config(const struct ether_addr *match_mac,
+bool net_match_config(Set *match_mac,
char * const *match_paths,
char * const *match_drivers,
char * const *match_types,
@@ -132,7 +132,7 @@ bool net_match_config(const struct ether_addr *match_mac,
if (match_arch && condition_test(match_arch) <= 0)
return false;
- if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))
+ if (match_mac && dev_mac && !set_contains(match_mac, dev_mac))
return false;
if (!net_condition_test_strv(match_paths, dev_path))
@@ -284,10 +284,9 @@ int config_parse_hwaddr(const char *unit,
const char *rvalue,
void *data,
void *userdata) {
+
+ _cleanup_free_ struct ether_addr *n = NULL;
struct ether_addr **hwaddr = data;
- struct ether_addr *n;
- const char *start;
- size_t offset;
int r;
assert(filename);
@@ -299,17 +298,86 @@ int config_parse_hwaddr(const char *unit,
if (!n)
return log_oom();
- start = rvalue + strspn(rvalue, WHITESPACE);
- r = ether_addr_from_string(start, n, &offset);
+ r = ether_addr_from_string(rvalue, n);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Not a valid MAC address, ignoring assignment: %s", rvalue);
+ return 0;
+ }
+
+ *hwaddr = TAKE_PTR(n);
+
+ return 0;
+}
+
+int config_parse_hwaddrs(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ _cleanup_set_free_free_ Set *s = NULL;
+ const char *p = rvalue;
+ Set **hwaddrs = data;
+ int r;
- if (r || (start[offset + strspn(start + offset, WHITESPACE)] != '\0')) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue);
- free(n);
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ if (isempty(rvalue)) {
+ /* Empty assignment resets the list */
+ *hwaddrs = set_free_free(*hwaddrs);
return 0;
}
- free(*hwaddr);
- *hwaddr = n;
+ s = set_new(&ether_addr_hash_ops);
+ if (!s)
+ return log_oom();
+
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+ _cleanup_free_ struct ether_addr *n = NULL;
+
+ r = extract_first_word(&p, &word, NULL, 0);
+ if (r == 0)
+ break;
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ n = new(struct ether_addr, 1);
+ if (!n)
+ return log_oom();
+
+ r = ether_addr_from_string(word, n);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring: %s", word);
+ continue;
+ }
+
+ r = set_put(s, n);
+ if (r < 0)
+ return log_oom();
+ if (r > 0)
+ n = NULL; /* avoid cleanup */
+ }
+
+ r = set_ensure_allocated(hwaddrs, &ether_addr_hash_ops);
+ if (r < 0)
+ return log_oom();
+
+ r = set_move(*hwaddrs, s);
+ if (r < 0)
+ return log_oom();
return 0;
}
@@ -592,14 +660,3 @@ int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t siz
return 0;
}
-
-int deserialize_dhcp_option(void **data, size_t *data_len, const char *string) {
- assert(data);
- assert(data_len);
- assert(string);
-
- if (strlen(string) % 2)
- return -EINVAL;
-
- return unhexmem(string, strlen(string), (void **)data, data_len);
-}
diff --git a/src/systemd/src/libsystemd-network/network-internal.h b/src/systemd/src/libsystemd-network/network-internal.h
index e7fc337e6b..d0076f453d 100644
--- a/src/systemd/src/libsystemd-network/network-internal.h
+++ b/src/systemd/src/libsystemd-network/network-internal.h
@@ -12,12 +12,13 @@
#include "sd-dhcp-lease.h"
#include "condition.h"
+#include "set.h"
#include "udev.h"
#define LINK_BRIDGE_PORT_PRIORITY_INVALID 128
#define LINK_BRIDGE_PORT_PRIORITY_MAX 63
-bool net_match_config(const struct ether_addr *match_mac,
+bool net_match_config(Set *match_mac,
char * const *match_path,
char * const *match_driver,
char * const *match_type,
@@ -42,6 +43,10 @@ int config_parse_hwaddr(const char *unit, const char *filename, unsigned line,
const char *section, unsigned section_line, const char *lvalue,
int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_hwaddrs(const char *unit, const char *filename, unsigned line,
+ const char *section, unsigned section_line, const char *lvalue,
+ int ltype, const char *rvalue, void *data, void *userdata);
+
int config_parse_ifnames(const char *unit, const char *filename, unsigned line,
const char *section, unsigned section_line, const char *lvalue,
int ltype, const char *rvalue, void *data, void *userdata);
@@ -73,5 +78,5 @@ struct sd_dhcp_route;
void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size);
int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string);
+/* It is not necessary to add deserialize_dhcp_option(). Use unhexmem() instead. */
int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size);
-int deserialize_dhcp_option(void **data, size_t *data_len, const char *string);
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
index d1bd1cc910..ef2620f437 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
@@ -29,6 +29,7 @@
#include "random-util.h"
#include "string-util.h"
#include "util.h"
+#include "strv.h"
#define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
#define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
@@ -85,6 +86,7 @@ struct sd_dhcp_client {
size_t client_id_len;
char *hostname;
char *vendor_class_identifier;
+ char **user_class;
uint32_t mtu;
uint32_t xid;
usec_t start_time;
@@ -445,6 +447,26 @@ int sd_dhcp_client_set_vendor_class_identifier(
return free_and_strdup(&client->vendor_class_identifier, vci);
}
+int sd_dhcp_client_set_user_class(
+ sd_dhcp_client *client,
+ const char* const* user_class) {
+
+ _cleanup_strv_free_ char **s = NULL;
+ char **p;
+
+ STRV_FOREACH(p, (char **) user_class)
+ if (strlen(*p) > 255)
+ return -ENAMETOOLONG;
+
+ s = strv_copy((char **) user_class);
+ if (!s)
+ return -ENOMEM;
+
+ client->user_class = TAKE_PTR(s);
+
+ return 0;
+}
+
int sd_dhcp_client_set_client_port(
sd_dhcp_client *client,
uint16_t port) {
@@ -768,6 +790,15 @@ static int client_send_discover(sd_dhcp_client *client) {
return r;
}
+ if (client->user_class) {
+ r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
+ SD_DHCP_OPTION_USER_CLASS,
+ strv_length(client->user_class),
+ client->user_class);
+ if (r < 0)
+ return r;
+ }
+
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_END, 0, NULL);
if (r < 0)
@@ -1923,6 +1954,7 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
free(client->req_opts);
free(client->hostname);
free(client->vendor_class_identifier);
+ client->user_class = strv_free(client->user_class);
return mfree(client);
}
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
index 591c1f3420..d92c512604 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
@@ -223,7 +223,7 @@ int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes) {
}
int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains) {
- unsigned r;
+ size_t r;
assert_return(lease, -EINVAL);
assert_return(domains, -EINVAL);
@@ -669,7 +669,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
return 0;
}
- if (!timezone_is_valid(tz)) {
+ if (!timezone_is_valid(tz, LOG_DEBUG)) {
log_debug_errno(r, "Timezone is not valid, ignoring: %m");
return 0;
}
@@ -1195,13 +1195,13 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
}
if (client_id_hex) {
- r = deserialize_dhcp_option(&lease->client_id, &lease->client_id_len, client_id_hex);
+ r = unhexmem(client_id_hex, (size_t) -1, &lease->client_id, &lease->client_id_len);
if (r < 0)
log_debug_errno(r, "Failed to parse client ID %s, ignoring: %m", client_id_hex);
}
if (vendor_specific_hex) {
- r = deserialize_dhcp_option(&lease->vendor_specific, &lease->vendor_specific_len, vendor_specific_hex);
+ r = unhexmem(vendor_specific_hex, (size_t) -1, &lease->vendor_specific, &lease->vendor_specific_len);
if (r < 0)
log_debug_errno(r, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex);
}
@@ -1213,7 +1213,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
if (!options[i])
continue;
- r = deserialize_dhcp_option(&data, &len, options[i]);
+ r = unhexmem(options[i], (size_t) -1, &data, &len);
if (r < 0) {
log_debug_errno(r, "Failed to parse private DHCP option %s, ignoring: %m", options[i]);
continue;
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
index 9ef3fab74f..3952cd99f0 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
@@ -250,8 +250,7 @@ int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval,
if (r < 0)
return 0;
- strv_free(lease->domains);
- lease->domains = domains;
+ strv_free_and_replace(lease->domains, domains);
lease->domains_count = r;
return r;
@@ -310,8 +309,7 @@ int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
if (r < 0)
return 0;
- lease->ntp_fqdn = strv_free(lease->ntp_fqdn);
- lease->ntp_fqdn = servers;
+ strv_free_and_replace(lease->ntp_fqdn, servers);
lease->ntp_fqdn_count = r;
break;
diff --git a/src/systemd/src/libsystemd-network/sd-lldp.c b/src/systemd/src/libsystemd-network/sd-lldp.c
index bb15d94ecf..d88a0c6f2d 100644
--- a/src/systemd/src/libsystemd-network/sd-lldp.c
+++ b/src/systemd/src/libsystemd-network/sd-lldp.c
@@ -404,15 +404,15 @@ static int neighbor_compare_func(const void *a, const void *b) {
static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) {
sd_lldp *lldp = userdata;
- int r, q;
+ int r;
r = lldp_make_space(lldp, 0);
if (r < 0)
return log_lldp_errno(r, "Failed to make space: %m");
- q = lldp_start_timer(lldp, NULL);
- if (q < 0)
- return log_lldp_errno(q, "Failed to restart timer: %m");
+ r = lldp_start_timer(lldp, NULL);
+ if (r < 0)
+ return log_lldp_errno(r, "Failed to restart timer: %m");
return 0;
}
diff --git a/src/systemd/src/systemd/sd-dhcp-client.h b/src/systemd/src/systemd/sd-dhcp-client.h
index 789cc50174..fd0a569362 100644
--- a/src/systemd/src/systemd/sd-dhcp-client.h
+++ b/src/systemd/src/systemd/sd-dhcp-client.h
@@ -82,6 +82,7 @@ enum {
SD_DHCP_OPTION_REBINDING_T2_TIME = 59,
SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60,
SD_DHCP_OPTION_CLIENT_IDENTIFIER = 61,
+ SD_DHCP_OPTION_USER_CLASS = 77,
SD_DHCP_OPTION_FQDN = 81,
SD_DHCP_OPTION_NEW_POSIX_TIMEZONE = 100,
SD_DHCP_OPTION_NEW_TZDB_TIMEZONE = 101,
@@ -154,6 +155,9 @@ int sd_dhcp_client_set_hostname(
int sd_dhcp_client_set_vendor_class_identifier(
sd_dhcp_client *client,
const char *vci);
+int sd_dhcp_client_set_user_class(
+ sd_dhcp_client *client,
+ const char* const *user_class);
int sd_dhcp_client_get_lease(
sd_dhcp_client *client,
sd_dhcp_lease **ret);