diff options
author | Thomas Haller <thaller@redhat.com> | 2018-08-24 15:46:13 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2018-08-26 15:48:17 +0200 |
commit | 8aa8d7471023aebed9b626a566fff9753a85e7ff (patch) | |
tree | 57cdd00e7ee0bd59c11e88b9617f90a122b44508 /src/systemd | |
parent | 353810ccc15b85b4e013fcc6903913c02aca1a0c (diff) | |
download | NetworkManager-8aa8d7471023aebed9b626a566fff9753a85e7ff.tar.gz |
systemd: update code from upstream (2018-08-26)
This is a direct dump from systemd git.
======
SYSTEMD_DIR=../systemd
COMMIT=56663345dfb1dd3ff23cac5fbc955aba54477efa
(
cd "$SYSTEMD_DIR"
git checkout "$COMMIT"
git reset --hard
git clean -fdx
)
git ls-files :/src/systemd/src/ \
:/shared/nm-utils/unaligned.h | \
xargs -d '\n' rm -f
nm_copy_sd() {
mkdir -p "./src/systemd/$(dirname "$1")"
cp "$SYSTEMD_DIR/$1" "./src/systemd/$1"
}
nm_copy_sd_shared() {
mkdir -p "./shared/nm-utils/"
cp "$SYSTEMD_DIR/$1" "./shared/nm-utils/${1##*/}"
}
nm_copy_sd "src/basic/alloc-util.c"
nm_copy_sd "src/basic/alloc-util.h"
nm_copy_sd "src/basic/async.h"
nm_copy_sd "src/basic/env-util.c"
nm_copy_sd "src/basic/env-util.h"
nm_copy_sd "src/basic/escape.c"
nm_copy_sd "src/basic/escape.h"
nm_copy_sd "src/basic/ether-addr-util.c"
nm_copy_sd "src/basic/ether-addr-util.h"
nm_copy_sd "src/basic/extract-word.c"
nm_copy_sd "src/basic/extract-word.h"
nm_copy_sd "src/basic/fileio.c"
nm_copy_sd "src/basic/fileio.h"
nm_copy_sd "src/basic/fd-util.c"
nm_copy_sd "src/basic/fd-util.h"
nm_copy_sd "src/basic/fs-util.c"
nm_copy_sd "src/basic/fs-util.h"
nm_copy_sd "src/basic/hash-funcs.c"
nm_copy_sd "src/basic/hash-funcs.h"
nm_copy_sd "src/basic/hashmap.c"
nm_copy_sd "src/basic/hashmap.h"
nm_copy_sd "src/basic/hexdecoct.c"
nm_copy_sd "src/basic/hexdecoct.h"
nm_copy_sd "src/basic/hostname-util.c"
nm_copy_sd "src/basic/hostname-util.h"
nm_copy_sd "src/basic/in-addr-util.c"
nm_copy_sd "src/basic/in-addr-util.h"
nm_copy_sd "src/basic/io-util.c"
nm_copy_sd "src/basic/io-util.h"
nm_copy_sd "src/basic/list.h"
nm_copy_sd "src/basic/log.h"
nm_copy_sd "src/basic/macro.h"
nm_copy_sd "src/basic/mempool.h"
nm_copy_sd "src/basic/mempool.c"
nm_copy_sd "src/basic/parse-util.c"
nm_copy_sd "src/basic/parse-util.h"
nm_copy_sd "src/basic/path-util.c"
nm_copy_sd "src/basic/path-util.h"
nm_copy_sd "src/basic/prioq.h"
nm_copy_sd "src/basic/prioq.c"
nm_copy_sd "src/basic/process-util.h"
nm_copy_sd "src/basic/process-util.c"
nm_copy_sd "src/basic/random-util.c"
nm_copy_sd "src/basic/random-util.h"
nm_copy_sd "src/basic/refcnt.h"
nm_copy_sd "src/basic/set.h"
nm_copy_sd "src/basic/signal-util.h"
nm_copy_sd "src/basic/siphash24.h"
nm_copy_sd "src/basic/socket-util.c"
nm_copy_sd "src/basic/socket-util.h"
nm_copy_sd "src/basic/sparse-endian.h"
nm_copy_sd "src/basic/stat-util.c"
nm_copy_sd "src/basic/stat-util.h"
nm_copy_sd "src/basic/stdio-util.h"
nm_copy_sd "src/basic/string-table.c"
nm_copy_sd "src/basic/string-table.h"
nm_copy_sd "src/basic/string-util.c"
nm_copy_sd "src/basic/string-util.h"
nm_copy_sd "src/basic/strv.c"
nm_copy_sd "src/basic/strv.h"
nm_copy_sd "src/basic/time-util.c"
nm_copy_sd "src/basic/time-util.h"
nm_copy_sd "src/basic/umask-util.h"
nm_copy_sd_shared "src/basic/unaligned.h"
nm_copy_sd "src/basic/utf8.c"
nm_copy_sd "src/basic/utf8.h"
nm_copy_sd "src/basic/util.c"
nm_copy_sd "src/basic/util.h"
nm_copy_sd "src/libsystemd-network/arp-util.c"
nm_copy_sd "src/libsystemd-network/arp-util.h"
nm_copy_sd "src/libsystemd-network/dhcp6-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp6-lease-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp6-network.c"
nm_copy_sd "src/libsystemd-network/dhcp6-option.c"
nm_copy_sd "src/libsystemd-network/dhcp6-protocol.h"
nm_copy_sd "src/libsystemd-network/dhcp-identifier.c"
nm_copy_sd "src/libsystemd-network/dhcp-identifier.h"
nm_copy_sd "src/libsystemd-network/dhcp-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp-lease-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp-network.c"
nm_copy_sd "src/libsystemd-network/dhcp-option.c"
nm_copy_sd "src/libsystemd-network/dhcp-packet.c"
nm_copy_sd "src/libsystemd-network/dhcp-protocol.h"
nm_copy_sd "src/libsystemd-network/lldp-internal.h"
nm_copy_sd "src/libsystemd-network/lldp-neighbor.c"
nm_copy_sd "src/libsystemd-network/lldp-neighbor.h"
nm_copy_sd "src/libsystemd-network/lldp-network.c"
nm_copy_sd "src/libsystemd-network/lldp-network.h"
nm_copy_sd "src/libsystemd-network/network-internal.c"
nm_copy_sd "src/libsystemd-network/network-internal.h"
nm_copy_sd "src/libsystemd-network/sd-dhcp6-client.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp6-lease.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp-client.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp-lease.c"
nm_copy_sd "src/libsystemd-network/sd-ipv4ll.c"
nm_copy_sd "src/libsystemd-network/sd-ipv4acd.c"
nm_copy_sd "src/libsystemd-network/sd-lldp.c"
nm_copy_sd "src/libsystemd/sd-event/sd-event.c"
nm_copy_sd "src/libsystemd/sd-id128/id128-util.c"
nm_copy_sd "src/libsystemd/sd-id128/id128-util.h"
nm_copy_sd "src/libsystemd/sd-id128/sd-id128.c"
nm_copy_sd "src/shared/dns-domain.c"
nm_copy_sd "src/shared/dns-domain.h"
nm_copy_sd "src/systemd/_sd-common.h"
nm_copy_sd "src/systemd/sd-dhcp6-client.h"
nm_copy_sd "src/systemd/sd-dhcp6-lease.h"
nm_copy_sd "src/systemd/sd-dhcp-client.h"
nm_copy_sd "src/systemd/sd-dhcp-lease.h"
nm_copy_sd "src/systemd/sd-event.h"
nm_copy_sd "src/systemd/sd-ndisc.h"
nm_copy_sd "src/systemd/sd-id128.h"
nm_copy_sd "src/systemd/sd-ipv4acd.h"
nm_copy_sd "src/systemd/sd-ipv4ll.h"
nm_copy_sd "src/systemd/sd-lldp.h"
Diffstat (limited to 'src/systemd')
67 files changed, 1494 insertions, 330 deletions
diff --git a/src/systemd/src/basic/env-util.c b/src/systemd/src/basic/env-util.c new file mode 100644 index 0000000000..a784a30e1d --- /dev/null +++ b/src/systemd/src/basic/env-util.c @@ -0,0 +1,785 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include <errno.h> +#include <limits.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "alloc-util.h" +#include "env-util.h" +#include "escape.h" +#include "extract-word.h" +#include "macro.h" +#include "parse-util.h" +#include "string-util.h" +#include "strv.h" +#include "utf8.h" + +#define VALID_CHARS_ENV_NAME \ + DIGITS LETTERS \ + "_" + +#ifndef ARG_MAX +#define ARG_MAX ((size_t) sysconf(_SC_ARG_MAX)) +#endif + +static bool env_name_is_valid_n(const char *e, size_t n) { + const char *p; + + if (!e) + return false; + + if (n <= 0) + return false; + + if (e[0] >= '0' && e[0] <= '9') + return false; + + /* POSIX says the overall size of the environment block cannot + * be > ARG_MAX, an individual assignment hence cannot be + * either. Discounting the equal sign and trailing NUL this + * hence leaves ARG_MAX-2 as longest possible variable + * name. */ + if (n > ARG_MAX - 2) + return false; + + for (p = e; p < e + n; p++) + if (!strchr(VALID_CHARS_ENV_NAME, *p)) + return false; + + return true; +} + +bool env_name_is_valid(const char *e) { + if (!e) + return false; + + return env_name_is_valid_n(e, strlen(e)); +} + +bool env_value_is_valid(const char *e) { + if (!e) + return false; + + if (!utf8_is_valid(e)) + return false; + + /* bash allows tabs and newlines in environment variables, and so + * should we */ + if (string_has_cc(e, "\t\n")) + return false; + + /* POSIX says the overall size of the environment block cannot + * be > ARG_MAX, an individual assignment hence cannot be + * either. Discounting the shortest possible variable name of + * length 1, the equal sign and trailing NUL this hence leaves + * ARG_MAX-3 as longest possible variable value. */ + if (strlen(e) > ARG_MAX - 3) + return false; + + return true; +} + +bool env_assignment_is_valid(const char *e) { + const char *eq; + + eq = strchr(e, '='); + if (!eq) + return false; + + if (!env_name_is_valid_n(e, eq - e)) + return false; + + if (!env_value_is_valid(eq + 1)) + return false; + + /* POSIX says the overall size of the environment block cannot + * be > ARG_MAX, hence the individual variable assignments + * cannot be either, but let's leave room for one trailing NUL + * byte. */ + if (strlen(e) > ARG_MAX - 1) + return false; + + return true; +} + +bool strv_env_is_valid(char **e) { + char **p, **q; + + STRV_FOREACH(p, e) { + size_t k; + + if (!env_assignment_is_valid(*p)) + return false; + + /* Check if there are duplicate assginments */ + k = strcspn(*p, "="); + STRV_FOREACH(q, p + 1) + if (strneq(*p, *q, k) && (*q)[k] == '=') + return false; + } + + return true; +} + +bool strv_env_name_is_valid(char **l) { + char **p, **q; + + STRV_FOREACH(p, l) { + if (!env_name_is_valid(*p)) + return false; + + STRV_FOREACH(q, p + 1) + if (streq(*p, *q)) + return false; + } + + return true; +} + +bool strv_env_name_or_assignment_is_valid(char **l) { + char **p, **q; + + STRV_FOREACH(p, l) { + if (!env_assignment_is_valid(*p) && !env_name_is_valid(*p)) + return false; + + STRV_FOREACH(q, p + 1) + if (streq(*p, *q)) + return false; + } + + return true; +} + +static int env_append(char **r, char ***k, char **a) { + assert(r); + assert(k); + + if (!a) + return 0; + + /* Add the entries of a to *k unless they already exist in *r + * in which case they are overridden instead. This assumes + * there is enough space in the r array. */ + + for (; *a; a++) { + char **j; + size_t n; + + n = strcspn(*a, "="); + + if ((*a)[n] == '=') + n++; + + for (j = r; j < *k; j++) + if (strneq(*j, *a, n)) + break; + + if (j >= *k) + (*k)++; + else + free(*j); + + *j = strdup(*a); + if (!*j) + return -ENOMEM; + } + + return 0; +} + +char **strv_env_merge(size_t n_lists, ...) { + size_t n = 0; + char **l, **k, **r; + va_list ap; + size_t i; + + /* Merges an arbitrary number of environment sets */ + + va_start(ap, n_lists); + for (i = 0; i < n_lists; i++) { + l = va_arg(ap, char**); + n += strv_length(l); + } + va_end(ap); + + r = new(char*, n+1); + if (!r) + return NULL; + + k = r; + + va_start(ap, n_lists); + for (i = 0; i < n_lists; i++) { + l = va_arg(ap, char**); + if (env_append(r, &k, l) < 0) + goto fail; + } + va_end(ap); + + *k = NULL; + + return r; + +fail: + va_end(ap); + strv_free(r); + + return NULL; +} + +static bool env_match(const char *t, const char *pattern) { + assert(t); + assert(pattern); + + /* pattern a matches string a + * a matches a= + * a matches a=b + * a= matches a= + * a=b matches a=b + * a= does not match a + * a=b does not match a= + * a=b does not match a + * a=b does not match a=c */ + + if (streq(t, pattern)) + return true; + + if (!strchr(pattern, '=')) { + size_t l = strlen(pattern); + + return strneq(t, pattern, l) && t[l] == '='; + } + + return false; +} + +static bool env_entry_has_name(const char *entry, const char *name) { + const char *t; + + assert(entry); + assert(name); + + t = startswith(entry, name); + if (!t) + return false; + + return *t == '='; +} + +char **strv_env_delete(char **x, size_t n_lists, ...) { + size_t n, i = 0; + char **k, **r; + va_list ap; + + /* Deletes every entry from x that is mentioned in the other + * string lists */ + + n = strv_length(x); + + r = new(char*, n+1); + if (!r) + return NULL; + + STRV_FOREACH(k, x) { + size_t v; + + va_start(ap, n_lists); + for (v = 0; v < n_lists; v++) { + char **l, **j; + + l = va_arg(ap, char**); + STRV_FOREACH(j, l) + if (env_match(*k, *j)) + goto skip; + } + va_end(ap); + + r[i] = strdup(*k); + if (!r[i]) { + strv_free(r); + return NULL; + } + + i++; + continue; + + skip: + va_end(ap); + } + + r[i] = NULL; + + assert(i <= n); + + return r; +} + +char **strv_env_unset(char **l, const char *p) { + + char **f, **t; + + if (!l) + return NULL; + + assert(p); + + /* Drops every occurrence of the env var setting p in the + * string list. Edits in-place. */ + + for (f = t = l; *f; f++) { + + if (env_match(*f, p)) { + free(*f); + continue; + } + + *(t++) = *f; + } + + *t = NULL; + return l; +} + +char **strv_env_unset_many(char **l, ...) { + + char **f, **t; + + if (!l) + return NULL; + + /* Like strv_env_unset() but applies many at once. Edits in-place. */ + + for (f = t = l; *f; f++) { + bool found = false; + const char *p; + va_list ap; + + va_start(ap, l); + + while ((p = va_arg(ap, const char*))) { + if (env_match(*f, p)) { + found = true; + break; + } + } + + va_end(ap); + + if (found) { + free(*f); + continue; + } + + *(t++) = *f; + } + + *t = NULL; + return l; +} + +int strv_env_replace(char ***l, char *p) { + char **f; + const char *t, *name; + + assert(p); + + /* Replace first occurrence of the env var or add a new one in the + * string list. Drop other occurences. Edits in-place. Does not copy p. + * p must be a valid key=value assignment. + */ + + t = strchr(p, '='); + assert(t); + + name = strndupa(p, t - p); + + for (f = *l; f && *f; f++) + if (env_entry_has_name(*f, name)) { + free_and_replace(*f, p); + strv_env_unset(f + 1, *f); + return 0; + } + + /* We didn't find a match, we need to append p or create a new strv */ + if (strv_push(l, p) < 0) + return -ENOMEM; + return 1; +} + +char **strv_env_set(char **x, const char *p) { + + char **k; + _cleanup_strv_free_ char **r = NULL; + char* m[2] = { (char*) p, NULL }; + + /* Overrides the env var setting of p, returns a new copy */ + + r = new(char*, strv_length(x)+2); + if (!r) + return NULL; + + k = r; + if (env_append(r, &k, x) < 0) + return NULL; + + if (env_append(r, &k, m) < 0) + return NULL; + + *k = NULL; + + return TAKE_PTR(r); +} + +char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) { + char **i; + + assert(name); + + if (k <= 0) + return NULL; + + STRV_FOREACH_BACKWARDS(i, l) + if (strneq(*i, name, k) && + (*i)[k] == '=') + return *i + k + 1; + + if (flags & REPLACE_ENV_USE_ENVIRONMENT) { + const char *t; + + t = strndupa(name, k); + return getenv(t); + }; + + return NULL; +} + +char *strv_env_get(char **l, const char *name) { + assert(name); + + return strv_env_get_n(l, name, strlen(name), 0); +} + +char **strv_env_clean_with_callback(char **e, void (*invalid_callback)(const char *p, void *userdata), void *userdata) { + char **p, **q; + int k = 0; + + STRV_FOREACH(p, e) { + size_t n; + bool duplicate = false; + + if (!env_assignment_is_valid(*p)) { + if (invalid_callback) + invalid_callback(*p, userdata); + free(*p); + continue; + } + + n = strcspn(*p, "="); + STRV_FOREACH(q, p + 1) + if (strneq(*p, *q, n) && (*q)[n] == '=') { + duplicate = true; + break; + } + + if (duplicate) { + free(*p); + continue; + } + + e[k++] = *p; + } + + if (e) + e[k] = NULL; + + return e; +} + +char *replace_env_n(const char *format, size_t n, char **env, unsigned flags) { + enum { + WORD, + CURLY, + VARIABLE, + VARIABLE_RAW, + TEST, + DEFAULT_VALUE, + ALTERNATE_VALUE, + } state = WORD; + + const char *e, *word = format, *test_value; + char *k; + _cleanup_free_ char *r = NULL; + size_t i, len; + int nest = 0; + + assert(format); + + for (e = format, i = 0; *e && i < n; e ++, i ++) + switch (state) { + + case WORD: + if (*e == '$') + state = CURLY; + break; + + case CURLY: + if (*e == '{') { + k = strnappend(r, word, e-word-1); + if (!k) + return NULL; + + free_and_replace(r, k); + + word = e-1; + state = VARIABLE; + nest++; + } else if (*e == '$') { + k = strnappend(r, word, e-word); + if (!k) + return NULL; + + free_and_replace(r, k); + + word = e+1; + state = WORD; + + } else if (flags & REPLACE_ENV_ALLOW_BRACELESS && strchr(VALID_CHARS_ENV_NAME, *e)) { + k = strnappend(r, word, e-word-1); + if (!k) + return NULL; + + free_and_replace(r, k); + + word = e-1; + state = VARIABLE_RAW; + + } else + state = WORD; + break; + + case VARIABLE: + if (*e == '}') { + const char *t; + + t = strv_env_get_n(env, word+2, e-word-2, flags); + + k = strappend(r, t); + if (!k) + return NULL; + + free_and_replace(r, k); + + word = e+1; + state = WORD; + } else if (*e == ':') { + if (!(flags & REPLACE_ENV_ALLOW_EXTENDED)) + /* Treat this as unsupported syntax, i.e. do no replacement */ + state = WORD; + else { + len = e-word-2; + state = TEST; + } + } + break; + + case TEST: + if (*e == '-') + state = DEFAULT_VALUE; + else if (*e == '+') + state = ALTERNATE_VALUE; + else { + state = WORD; + break; + } + + test_value = e+1; + break; + + case DEFAULT_VALUE: /* fall through */ + case ALTERNATE_VALUE: + assert(flags & REPLACE_ENV_ALLOW_EXTENDED); + + if (*e == '{') { + nest++; + break; + } + + if (*e != '}') + break; + + nest--; + if (nest == 0) { + const char *t; + _cleanup_free_ char *v = NULL; + + t = strv_env_get_n(env, word+2, len, flags); + + if (t && state == ALTERNATE_VALUE) + t = v = replace_env_n(test_value, e-test_value, env, flags); + else if (!t && state == DEFAULT_VALUE) + t = v = replace_env_n(test_value, e-test_value, env, flags); + + k = strappend(r, t); + if (!k) + return NULL; + + free_and_replace(r, k); + + word = e+1; + state = WORD; + } + break; + + case VARIABLE_RAW: + assert(flags & REPLACE_ENV_ALLOW_BRACELESS); + + if (!strchr(VALID_CHARS_ENV_NAME, *e)) { + const char *t; + + t = strv_env_get_n(env, word+1, e-word-1, flags); + + k = strappend(r, t); + if (!k) + return NULL; + + free_and_replace(r, k); + + word = e--; + i--; + state = WORD; + } + break; + } + + if (state == VARIABLE_RAW) { + const char *t; + + assert(flags & REPLACE_ENV_ALLOW_BRACELESS); + + t = strv_env_get_n(env, word+1, e-word-1, flags); + return strappend(r, t); + } else + return strnappend(r, word, e-word); +} + +char **replace_env_argv(char **argv, char **env) { + char **ret, **i; + size_t k = 0, l = 0; + + l = strv_length(argv); + + ret = new(char*, l+1); + if (!ret) + return NULL; + + STRV_FOREACH(i, argv) { + + /* If $FOO appears as single word, replace it by the split up variable */ + if ((*i)[0] == '$' && !IN_SET((*i)[1], '{', '$')) { + char *e; + char **w, **m = NULL; + size_t q; + + e = strv_env_get(env, *i+1); + if (e) { + int r; + + r = strv_split_extract(&m, e, WHITESPACE, EXTRACT_RELAX|EXTRACT_QUOTES); + if (r < 0) { + ret[k] = NULL; + strv_free(ret); + return NULL; + } + } else + m = NULL; + + q = strv_length(m); + l = l + q - 1; + + w = reallocarray(ret, l + 1, sizeof(char *)); + if (!w) { + ret[k] = NULL; + strv_free(ret); + strv_free(m); + return NULL; + } + + ret = w; + if (m) { + memcpy(ret + k, m, q * sizeof(char*)); + free(m); + } + + k += q; + continue; + } + + /* If ${FOO} appears as part of a word, replace it by the variable as-is */ + ret[k] = replace_env(*i, env, 0); + if (!ret[k]) { + strv_free(ret); + return NULL; + } + k++; + } + + ret[k] = NULL; + return ret; +} + +int getenv_bool(const char *p) { + const char *e; + + e = getenv(p); + if (!e) + return -ENXIO; + + return parse_boolean(e); +} + +int getenv_bool_secure(const char *p) { + const char *e; + + e = secure_getenv(p); + if (!e) + return -ENXIO; + + return parse_boolean(e); +} + +int serialize_environment(FILE *f, char **environment) { + char **e; + + STRV_FOREACH(e, environment) { + _cleanup_free_ char *ce; + + ce = cescape(*e); + if (!ce) + return -ENOMEM; + + fprintf(f, "env=%s\n", ce); + } + + /* caller should call ferror() */ + + return 0; +} + +int deserialize_environment(char ***environment, const char *line) { + char *uce; + int r; + + assert(line); + assert(environment); + + assert(startswith(line, "env=")); + r = cunescape(line + 4, 0, &uce); + if (r < 0) + return r; + + return strv_env_replace(environment, uce); +} diff --git a/src/systemd/src/basic/env-util.h b/src/systemd/src/basic/env-util.h new file mode 100644 index 0000000000..174433ea91 --- /dev/null +++ b/src/systemd/src/basic/env-util.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include <stdbool.h> +#include <stddef.h> +#include <stdio.h> + +#include "macro.h" +#include "string.h" + +bool env_name_is_valid(const char *e); +bool env_value_is_valid(const char *e); +bool env_assignment_is_valid(const char *e); + +enum { + REPLACE_ENV_USE_ENVIRONMENT = 1u, + REPLACE_ENV_ALLOW_BRACELESS = 2u, + REPLACE_ENV_ALLOW_EXTENDED = 4u, +}; + +char *replace_env_n(const char *format, size_t n, char **env, unsigned flags); +char **replace_env_argv(char **argv, char **env); + +static inline char *replace_env(const char *format, char **env, unsigned flags) { + return replace_env_n(format, strlen(format), env, flags); +} + +bool strv_env_is_valid(char **e); +#define strv_env_clean(l) strv_env_clean_with_callback(l, NULL, NULL) +char **strv_env_clean_with_callback(char **l, void (*invalid_callback)(const char *p, void *userdata), void *userdata); + +bool strv_env_name_is_valid(char **l); +bool strv_env_name_or_assignment_is_valid(char **l); + +char **strv_env_merge(size_t n_lists, ...); +char **strv_env_delete(char **x, size_t n_lists, ...); /* New copy */ + +char **strv_env_set(char **x, const char *p); /* New copy ... */ +char **strv_env_unset(char **l, const char *p); /* In place ... */ +char **strv_env_unset_many(char **l, ...) _sentinel_; +int strv_env_replace(char ***l, char *p); /* In place ... */ + +char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) _pure_; +char *strv_env_get(char **x, const char *n) _pure_; + +int getenv_bool(const char *p); +int getenv_bool_secure(const char *p); + +int serialize_environment(FILE *f, char **environment); +int deserialize_environment(char ***environment, const char *line); diff --git a/src/systemd/src/basic/ether-addr-util.c b/src/systemd/src/basic/ether-addr-util.c index a7f13ef06f..461ace73e2 100644 --- a/src/systemd/src/basic/ether-addr-util.c +++ b/src/systemd/src/basic/ether-addr-util.c @@ -1,7 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - Copyright © 2014 Tom Gundersen -***/ #include <errno.h> #include <net/ethernet.h> diff --git a/src/systemd/src/basic/ether-addr-util.h b/src/systemd/src/basic/ether-addr-util.h index f02cefead3..3be0370049 100644 --- a/src/systemd/src/basic/ether-addr-util.h +++ b/src/systemd/src/basic/ether-addr-util.h @@ -1,10 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - Copyright © 2014 Tom Gundersen -***/ - #include <net/ethernet.h> #include <stdbool.h> diff --git a/src/systemd/src/basic/fd-util.h b/src/systemd/src/basic/fd-util.h index 8adc959da8..00303a7e45 100644 --- a/src/systemd/src/basic/fd-util.h +++ b/src/systemd/src/basic/fd-util.h @@ -78,8 +78,12 @@ int acquire_data_fd(const void *data, size_t size, unsigned flags); int fd_duplicate_data_fd(int fd); /* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */ -#define ERRNO_IS_DISCONNECT(r) \ - IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH) +/* The kernel sends e.g., EHOSTUNREACH or ENONET to userspace in some ICMP error cases. + * See the icmp_err_convert[] in net/ipv4/icmp.c in the kernel sources */ +#define ERRNO_IS_DISCONNECT(r) \ + IN_SET(r, \ + ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, \ + ENETUNREACH, EHOSTUNREACH, ENOPROTOOPT, EHOSTDOWN, ENONET) /* Resource exhaustion, could be our fault or general system trouble */ #define ERRNO_IS_RESOURCE(r) \ diff --git a/src/systemd/src/basic/fileio.c b/src/systemd/src/basic/fileio.c index 6b0bad5b71..ea607f8cfb 100644 --- a/src/systemd/src/basic/fileio.c +++ b/src/systemd/src/basic/fileio.c @@ -1225,9 +1225,13 @@ int tempfn_xxxxxx(const char *p, const char *extra, char **ret) { const char *fn; char *t; - assert(p); assert(ret); + if (isempty(p)) + return -EINVAL; + if (path_equal(p, "/")) + return -EINVAL; + /* * Turns this: * /foo/bar/waldo @@ -1258,9 +1262,13 @@ int tempfn_random(const char *p, const char *extra, char **ret) { uint64_t u; unsigned i; - assert(p); assert(ret); + if (isempty(p)) + return -EINVAL; + if (path_equal(p, "/")) + return -EINVAL; + /* * Turns this: * /foo/bar/waldo @@ -1319,7 +1327,10 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) { if (!t) return -ENOMEM; - x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra); + if (isempty(p)) + x = stpcpy(stpcpy(t, ".#"), extra); + else + x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra); u = random_u64(); for (i = 0; i < 16; i++) { @@ -1404,7 +1415,8 @@ int open_tmpfile_unlinkable(const char *directory, int flags) { r = tmp_dir(&directory); if (r < 0) return r; - } + } else if (isempty(directory)) + return -EINVAL; /* Returns an unlinked temporary file that cannot be linked into the file system anymore */ @@ -1439,22 +1451,14 @@ int open_tmpfile_linkable(const char *target, int flags, char **ret_path) { * which case "ret_path" will be returned as NULL. If not possible a the tempoary path name used is returned in * "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */ - { - _cleanup_free_ char *dn = NULL; - - dn = dirname_malloc(target); - if (!dn) - return -ENOMEM; - - fd = open(dn, O_TMPFILE|flags, 0640); - if (fd >= 0) { - *ret_path = NULL; - return fd; - } - - log_debug_errno(errno, "Failed to use O_TMPFILE on %s: %m", dn); + fd = open_parent(target, O_TMPFILE|flags, 0640); + if (fd >= 0) { + *ret_path = NULL; + return fd; } + log_debug_errno(fd, "Failed to use O_TMPFILE for %s: %m", target); + r = tempfn_random(target, NULL, &tmp); if (r < 0) return r; diff --git a/src/systemd/src/basic/fs-util.c b/src/systemd/src/basic/fs-util.c index 3a8b32d881..09fcc32e0e 100644 --- a/src/systemd/src/basic/fs-util.c +++ b/src/systemd/src/basic/fs-util.c @@ -435,6 +435,31 @@ int mkfifo_atomic(const char *path, mode_t mode) { return 0; } +int mkfifoat_atomic(int dirfd, const char *path, mode_t mode) { + _cleanup_free_ char *t = NULL; + int r; + + assert(path); + + if (path_is_absolute(path)) + return mkfifo_atomic(path, mode); + + /* We're only interested in the (random) filename. */ + r = tempfn_random_child("", NULL, &t); + if (r < 0) + return r; + + if (mkfifoat(dirfd, t, mode) < 0) + return -errno; + + if (renameat(dirfd, t, dirfd, path) < 0) { + unlink_noerrno(t); + return -errno; + } + + return 0; +} + int get_files_in_directory(const char *path, char ***list) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; @@ -670,7 +695,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, if (!original_root && !ret && (flags & (CHASE_NONEXISTENT|CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_OPEN|CHASE_STEP)) == CHASE_OPEN) { /* Shortcut the CHASE_OPEN case if the caller isn't interested in the actual path and has no root set * and doesn't care about any of the other special features we provide either. */ - r = open(path, O_PATH|O_CLOEXEC); + r = open(path, O_PATH|O_CLOEXEC|((flags & CHASE_NOFOLLOW) ? O_NOFOLLOW : 0)); if (r < 0) return -errno; @@ -825,7 +850,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, fd_is_fs_type(child, AUTOFS_SUPER_MAGIC) > 0) return -EREMOTE; - if (S_ISLNK(st.st_mode)) { + if (S_ISLNK(st.st_mode) && !((flags & CHASE_NOFOLLOW) && isempty(todo))) { char *joined; _cleanup_free_ char *destination = NULL; @@ -1156,7 +1181,7 @@ int unlinkat_deallocate(int fd, const char *name, int flags) { } int fsync_directory_of_file(int fd) { - _cleanup_free_ char *path = NULL, *dn = NULL; + _cleanup_free_ char *path = NULL; _cleanup_close_ int dfd = -1; int r; @@ -1182,16 +1207,40 @@ int fsync_directory_of_file(int fd) { if (!path_is_absolute(path)) return -EINVAL; - dn = dirname_malloc(path); - if (!dn) - return -ENOMEM; - - dfd = open(dn, O_RDONLY|O_CLOEXEC|O_DIRECTORY); + dfd = open_parent(path, O_CLOEXEC, 0); if (dfd < 0) - return -errno; + return dfd; if (fsync(dfd) < 0) return -errno; return 0; } + +int open_parent(const char *path, int flags, mode_t mode) { + _cleanup_free_ char *parent = NULL; + int fd; + + if (isempty(path)) + return -EINVAL; + if (path_equal(path, "/")) /* requesting the parent of the root dir is fishy, let's prohibit that */ + return -EINVAL; + + parent = dirname_malloc(path); + if (!parent) + return -ENOMEM; + + /* Let's insist on O_DIRECTORY since the parent of a file or directory is a directory. Except if we open an + * O_TMPFILE file, because in that case we are actually create a regular file below the parent directory. */ + + if ((flags & O_PATH) == O_PATH) + flags |= O_DIRECTORY; + else if ((flags & O_TMPFILE) != O_TMPFILE) + flags |= O_DIRECTORY|O_RDONLY; + + fd = open(parent, flags, mode); + if (fd < 0) + return -errno; + + return fd; +} diff --git a/src/systemd/src/basic/fs-util.h b/src/systemd/src/basic/fs-util.h index 28566773c6..4b65625861 100644 --- a/src/systemd/src/basic/fs-util.h +++ b/src/systemd/src/basic/fs-util.h @@ -42,6 +42,7 @@ int symlink_idempotent(const char *from, const char *to); int symlink_atomic(const char *from, const char *to); int mknod_atomic(const char *path, mode_t mode, dev_t dev); int mkfifo_atomic(const char *path, mode_t mode); +int mkfifoat_atomic(int dir_fd, const char *path, mode_t mode); int get_files_in_directory(const char *path, char ***list); @@ -72,6 +73,7 @@ enum { CHASE_OPEN = 1 << 4, /* If set, return an O_PATH object to the final component */ CHASE_TRAIL_SLASH = 1 << 5, /* If set, any trailing slash will be preserved */ CHASE_STEP = 1 << 6, /* If set, 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. */ }; /* How many iterations to execute before returning -ELOOP */ @@ -103,3 +105,5 @@ void unlink_tempfilep(char (*p)[]); int unlinkat_deallocate(int fd, const char *name, int flags); int fsync_directory_of_file(int fd); + +int open_parent(const char *path, int flags, mode_t mode); diff --git a/src/systemd/src/basic/hash-funcs.c b/src/systemd/src/basic/hash-funcs.c index 2892346886..6f6832d237 100644 --- a/src/systemd/src/basic/hash-funcs.c +++ b/src/systemd/src/basic/hash-funcs.c @@ -1,7 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - Copyright © 2014 Michal Schmidt -***/ #include <string.h> @@ -74,7 +71,7 @@ void trivial_hash_func(const void *p, struct siphash *state) { } int trivial_compare_func(const void *a, const void *b) { - return a < b ? -1 : (a > b ? 1 : 0); + return CMP(a, b); } const struct hash_ops trivial_hash_ops = { @@ -90,7 +87,7 @@ int uint64_compare_func(const void *_a, const void *_b) { uint64_t a, b; a = *(const uint64_t*) _a; b = *(const uint64_t*) _b; - return a < b ? -1 : (a > b ? 1 : 0); + return CMP(a, b); } const struct hash_ops uint64_hash_ops = { @@ -107,7 +104,7 @@ int devt_compare_func(const void *_a, const void *_b) { dev_t a, b; a = *(const dev_t*) _a; b = *(const dev_t*) _b; - return a < b ? -1 : (a > b ? 1 : 0); + return CMP(a, b); } const struct hash_ops devt_hash_ops = { diff --git a/src/systemd/src/basic/hash-funcs.h b/src/systemd/src/basic/hash-funcs.h index 3715c56e07..fa45cfe256 100644 --- a/src/systemd/src/basic/hash-funcs.h +++ b/src/systemd/src/basic/hash-funcs.h @@ -1,10 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - Copyright © 2014 Michal Schmidt -***/ - #include "macro.h" #include "siphash24.h" diff --git a/src/systemd/src/basic/hashmap.c b/src/systemd/src/basic/hashmap.c index df9660560a..44d718c83d 100644 --- a/src/systemd/src/basic/hashmap.c +++ b/src/systemd/src/basic/hashmap.c @@ -1,7 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - Copyright © 2014 Michal Schmidt -***/ #include <errno.h> #include <stdint.h> @@ -9,8 +6,9 @@ #include <string.h> #include "alloc-util.h" -#include "hashmap.h" +#include "env-util.h" #include "fileio.h" +#include "hashmap.h" #include "macro.h" #include "mempool.h" #include "process-util.h" @@ -769,20 +767,31 @@ static void reset_direct_storage(HashmapBase *h) { memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets); } +static bool use_pool(void) { + static int b = -1; + + if (!is_main_thread()) + return false; + + if (b < 0) + b = getenv_bool("SYSTEMD_MEMPOOL") != 0; + + return b; +} + static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) { HashmapBase *h; const struct hashmap_type_info *hi = &hashmap_type_info[type]; - bool use_pool; + bool up; - use_pool = is_main_thread(); - - h = use_pool ? mempool_alloc0_tile(hi->mempool) : malloc0(hi->head_size); + up = use_pool(); + h = up ? mempool_alloc0_tile(hi->mempool) : malloc0(hi->head_size); if (!h) return NULL; h->type = type; - h->from_pool = use_pool; + h->from_pool = up; h->hash_ops = hash_ops ? hash_ops : &trivial_hash_ops; if (type == HASHMAP_TYPE_ORDERED) { @@ -860,9 +869,11 @@ static void hashmap_free_no_clear(HashmapBase *h) { assert_se(pthread_mutex_unlock(&hashmap_debug_list_mutex) == 0); #endif - if (h->from_pool) + if (h->from_pool) { + /* Ensure that the object didn't get migrated between threads. */ + assert_se(is_main_thread()); mempool_free_tile(hashmap_type_info[h->type].mempool, h); - else + } else free(h); } diff --git a/src/systemd/src/basic/hashmap.h b/src/systemd/src/basic/hashmap.h index d1d1b9c8a4..274afb395c 100644 --- a/src/systemd/src/basic/hashmap.h +++ b/src/systemd/src/basic/hashmap.h @@ -1,10 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - Copyright © 2014 Michal Schmidt -***/ - #include <limits.h> #include <stdbool.h> #include <stddef.h> diff --git a/src/systemd/src/basic/in-addr-util.c b/src/systemd/src/basic/in-addr-util.c index aed7601d50..d83658eaa7 100644 --- a/src/systemd/src/basic/in-addr-util.c +++ b/src/systemd/src/basic/in-addr-util.c @@ -571,3 +571,26 @@ int in_addr_prefix_from_string_auto( return 0; } + +void in_addr_data_hash_func(const void *p, struct siphash *state) { + const struct in_addr_data *a = p; + + siphash24_compress(&a->family, sizeof(a->family), state); + siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(a->family), state); +} + +int in_addr_data_compare_func(const void *a, const void *b) { + const struct in_addr_data *x = a, *y = b; + int r; + + r = CMP(x->family, y->family); + if (r != 0) + return r; + + return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family)); +} + +const struct hash_ops in_addr_data_hash_ops = { + .hash = in_addr_data_hash_func, + .compare = in_addr_data_compare_func, +}; diff --git a/src/systemd/src/basic/in-addr-util.h b/src/systemd/src/basic/in-addr-util.h index 956c00a850..e4be30dc0d 100644 --- a/src/systemd/src/basic/in-addr-util.h +++ b/src/systemd/src/basic/in-addr-util.h @@ -5,6 +5,7 @@ #include <stddef.h> #include <sys/socket.h> +#include "hash-funcs.h" #include "macro.h" #include "util.h" @@ -53,3 +54,7 @@ static inline size_t FAMILY_ADDRESS_SIZE(int family) { } #define IN_ADDR_NULL ((union in_addr_union) {}) + +void in_addr_data_hash_func(const void *p, struct siphash *state); +int in_addr_data_compare_func(const void *a, const void *b); +extern const struct hash_ops in_addr_data_hash_ops; diff --git a/src/systemd/src/basic/macro.h b/src/systemd/src/basic/macro.h index d1365f7058..24fcdc8400 100644 --- a/src/systemd/src/basic/macro.h +++ b/src/systemd/src/basic/macro.h @@ -7,7 +7,7 @@ #include <sys/sysmacros.h> #include <sys/types.h> -#define _printf_(a,b) __attribute__ ((format (printf, a, b))) +#define _printf_(a, b) __attribute__ ((format (printf, a, b))) #ifdef __clang__ # define _alloc_(...) #else @@ -22,8 +22,8 @@ #define _packed_ __attribute__ ((packed)) #define _malloc_ __attribute__ ((malloc)) #define _weak_ __attribute__ ((weak)) -#define _likely_(x) (__builtin_expect(!!(x),1)) -#define _unlikely_(x) (__builtin_expect(!!(x),0)) +#define _likely_(x) (__builtin_expect(!!(x), 1)) +#define _unlikely_(x) (__builtin_expect(!!(x), 0)) #define _public_ __attribute__ ((visibility("default"))) #define _hidden_ __attribute__ ((visibility("hidden"))) #define _weakref_(x) __attribute__((weakref(#x))) @@ -146,10 +146,10 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { # define VOID_0 ((void*)0) #endif -#define ELEMENTSOF(x) \ - __extension__ (__builtin_choose_expr( \ +#define ELEMENTSOF(x) \ + (__builtin_choose_expr( \ !__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \ - sizeof(x)/sizeof((x)[0]), \ + sizeof(x)/sizeof((x)[0]), \ VOID_0)) /* @@ -167,23 +167,23 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { */ #define container_of(ptr, type, member) __container_of(UNIQ, (ptr), type, member) #define __container_of(uniq, ptr, type, member) \ - __extension__ ({ \ + ({ \ const typeof( ((type*)0)->member ) *UNIQ_T(A, uniq) = (ptr); \ - (type*)( (char *)UNIQ_T(A, uniq) - offsetof(type,member) ); \ + (type*)( (char *)UNIQ_T(A, uniq) - offsetof(type, member) ); \ }) #undef MAX #define MAX(a, b) __MAX(UNIQ, (a), UNIQ, (b)) #define __MAX(aq, a, bq, b) \ - __extension__ ({ \ + ({ \ const typeof(a) UNIQ_T(A, aq) = (a); \ const typeof(b) UNIQ_T(B, bq) = (b); \ - UNIQ_T(A,aq) > UNIQ_T(B,bq) ? UNIQ_T(A,aq) : UNIQ_T(B,bq); \ + UNIQ_T(A, aq) > UNIQ_T(B, bq) ? UNIQ_T(A, aq) : UNIQ_T(B, bq); \ }) /* evaluates to (void) if _A or _B are not constant or of different types */ #define CONST_MAX(_A, _B) \ - __extension__ (__builtin_choose_expr( \ + (__builtin_choose_expr( \ __builtin_constant_p(_A) && \ __builtin_constant_p(_B) && \ __builtin_types_compatible_p(typeof(_A), typeof(_B)), \ @@ -193,47 +193,56 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { /* takes two types and returns the size of the larger one */ #define MAXSIZE(A, B) (sizeof(union _packed_ { typeof(A) a; typeof(B) b; })) -#define MAX3(x,y,z) \ - __extension__ ({ \ - const typeof(x) _c = MAX(x,y); \ - MAX(_c, z); \ - }) +#define MAX3(x, y, z) \ + ({ \ + const typeof(x) _c = MAX(x, y); \ + MAX(_c, z); \ + }) #undef MIN #define MIN(a, b) __MIN(UNIQ, (a), UNIQ, (b)) #define __MIN(aq, a, bq, b) \ - __extension__ ({ \ + ({ \ const typeof(a) UNIQ_T(A, aq) = (a); \ const typeof(b) UNIQ_T(B, bq) = (b); \ - UNIQ_T(A,aq) < UNIQ_T(B,bq) ? UNIQ_T(A,aq) : UNIQ_T(B,bq); \ + UNIQ_T(A, aq) < UNIQ_T(B, bq) ? UNIQ_T(A, aq) : UNIQ_T(B, bq); \ }) -#define MIN3(x,y,z) \ - __extension__ ({ \ - const typeof(x) _c = MIN(x,y); \ - MIN(_c, z); \ - }) +#define MIN3(x, y, z) \ + ({ \ + const typeof(x) _c = MIN(x, y); \ + MIN(_c, z); \ + }) #define LESS_BY(a, b) __LESS_BY(UNIQ, (a), UNIQ, (b)) #define __LESS_BY(aq, a, bq, b) \ - __extension__ ({ \ + ({ \ + const typeof(a) UNIQ_T(A, aq) = (a); \ + const typeof(b) UNIQ_T(B, bq) = (b); \ + UNIQ_T(A, aq) > UNIQ_T(B, bq) ? UNIQ_T(A, aq) - UNIQ_T(B, bq) : 0; \ + }) + +#define CMP(a, b) __CMP(UNIQ, (a), UNIQ, (b)) +#define __CMP(aq, a, bq, b) \ + ({ \ const typeof(a) UNIQ_T(A, aq) = (a); \ const typeof(b) UNIQ_T(B, bq) = (b); \ - UNIQ_T(A,aq) > UNIQ_T(B,bq) ? UNIQ_T(A,aq) - UNIQ_T(B,bq) : 0; \ + UNIQ_T(A, aq) < UNIQ_T(B, bq) ? -1 : \ + UNIQ_T(A, aq) > UNIQ_T(B, bq) ? 1 : 0; \ }) #undef CLAMP #define CLAMP(x, low, high) __CLAMP(UNIQ, (x), UNIQ, (low), UNIQ, (high)) #define __CLAMP(xq, x, lowq, low, highq, high) \ - __extension__ ({ \ - const typeof(x) UNIQ_T(X,xq) = (x); \ - const typeof(low) UNIQ_T(LOW,lowq) = (low); \ - const typeof(high) UNIQ_T(HIGH,highq) = (high); \ - UNIQ_T(X,xq) > UNIQ_T(HIGH,highq) ? \ - UNIQ_T(HIGH,highq) : \ - UNIQ_T(X,xq) < UNIQ_T(LOW,lowq) ? \ - UNIQ_T(LOW,lowq) : \ - UNIQ_T(X,xq); \ + ({ \ + const typeof(x) UNIQ_T(X, xq) = (x); \ + const typeof(low) UNIQ_T(LOW, lowq) = (low); \ + const typeof(high) UNIQ_T(HIGH, highq) = (high); \ + UNIQ_T(X, xq) > UNIQ_T(HIGH, highq) ? \ + UNIQ_T(HIGH, highq) : \ + UNIQ_T(X, xq) < UNIQ_T(LOW, lowq) ? \ + UNIQ_T(LOW, lowq) : \ + UNIQ_T(X, xq); \ }) /* [(x + y - 1) / y] suffers from an integer overflow, even though the @@ -241,18 +250,54 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { * [x / y + !!(x % y)]. Note that on "Real CPUs" a division returns both the * quotient and the remainder, so both should be equally fast. */ #define DIV_ROUND_UP(_x, _y) \ - __extension__ ({ \ + ({ \ const typeof(_x) __x = (_x); \ const typeof(_y) __y = (_y); \ (__x / __y + !!(__x % __y)); \ }) +#ifdef __COVERITY__ + +/* Use special definitions of assertion macros in order to prevent + * false positives of ASSERT_SIDE_EFFECT on Coverity static analyzer + * for uses of assert_se() and assert_return(). + * + * These definitions make expression go through a (trivial) function + * call to ensure they are not discarded. Also use ! or !! to ensure + * the boolean expressions are seen as such. + * + * This technique has been described and recommended in: + * https://community.synopsys.com/s/question/0D534000046Yuzb/suppressing-assertsideeffect-for-functions-that-allow-for-sideeffects + */ + +extern void __coverity_panic__(void); + +static inline int __coverity_check__(int condition) { + return condition; +} + +#define assert_message_se(expr, message) \ + do { \ + if (__coverity_check__(!(expr))) \ + __coverity_panic__(); \ + } while (false) + +#define assert_log(expr, message) __coverity_check__(!!(expr)) + +#else /* ! __COVERITY__ */ + #define assert_message_se(expr, message) \ do { \ if (_unlikely_(!(expr))) \ log_assert_failed(message, __FILE__, __LINE__, __PRETTY_FUNCTION__); \ } while (false) +#define assert_log(expr, message) ((_likely_(expr)) \ + ? (true) \ + : (log_assert_failed_return(message, __FILE__, __LINE__, __PRETTY_FUNCTION__), false)) + +#endif /* __COVERITY__ */ + #define assert_se(expr) assert_message_se(expr, #expr) /* We override the glibc assert() here. */ @@ -285,10 +330,6 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { REENABLE_WARNING #endif -#define assert_log(expr, message) ((_likely_(expr)) \ - ? (true) \ - : (log_assert_failed_return(message, __FILE__, __LINE__, __PRETTY_FUNCTION__), false)) - #define assert_return(expr, r) \ do { \ if (!assert_log(expr, #expr)) \ diff --git a/src/systemd/src/basic/mempool.c b/src/systemd/src/basic/mempool.c index 567f6b916e..a5ec8a1020 100644 --- a/src/systemd/src/basic/mempool.c +++ b/src/systemd/src/basic/mempool.c @@ -1,7 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - Copyright © 2014 Michal Schmidt -***/ #include <stdint.h> #include <stdlib.h> diff --git a/src/systemd/src/basic/mempool.h b/src/systemd/src/basic/mempool.h index 291415deb0..4098535c6f 100644 --- a/src/systemd/src/basic/mempool.h +++ b/src/systemd/src/basic/mempool.h @@ -1,10 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - Copyright © 2014 Michal Schmidt -***/ - #include <stddef.h> struct pool; diff --git a/src/systemd/src/basic/parse-util.c b/src/systemd/src/basic/parse-util.c index 6becf85878..db38f91c83 100644 --- a/src/systemd/src/basic/parse-util.c +++ b/src/systemd/src/basic/parse-util.c @@ -637,6 +637,8 @@ int parse_permille_unbounded(const char *p) { r = safe_atoi(n, &v); if (r < 0) return r; + if (v < 0) + return -ERANGE; } else { pc = endswith(p, "%"); if (!pc) @@ -657,15 +659,14 @@ int parse_permille_unbounded(const char *p) { r = safe_atoi(n, &v); if (r < 0) return r; + if (v < 0) + return -ERANGE; if (v > (INT_MAX - q) / 10) return -ERANGE; v = v * 10 + q; } - if (v < 0) - return -ERANGE; - return v; } diff --git a/src/systemd/src/basic/path-util.c b/src/systemd/src/basic/path-util.c index d214c72916..b62786f27e 100644 --- a/src/systemd/src/basic/path-util.c +++ b/src/systemd/src/basic/path-util.c @@ -110,10 +110,7 @@ int path_make_absolute_cwd(const char *p, char **ret) { if (r < 0) return r; - if (endswith(cwd, "/")) - c = strjoin(cwd, p); - else - c = strjoin(cwd, "/", p); + c = path_join(NULL, cwd, p); } if (!c) return -ENOMEM; diff --git a/src/systemd/src/basic/path-util.h b/src/systemd/src/basic/path-util.h index 8277c6b916..49604eab80 100644 --- a/src/systemd/src/basic/path-util.h +++ b/src/systemd/src/basic/path-util.h @@ -58,10 +58,10 @@ static inline bool path_equal_ptr(const char *a, const char *b) { /* Note: the search terminates on the first NULL item. */ #define PATH_IN_SET(p, ...) \ ({ \ - char **s; \ + char **_s; \ bool _found = false; \ - STRV_FOREACH(s, STRV_MAKE(__VA_ARGS__)) \ - if (path_equal(p, *s)) { \ + STRV_FOREACH(_s, STRV_MAKE(__VA_ARGS__)) \ + if (path_equal(p, *_s)) { \ _found = true; \ break; \ } \ diff --git a/src/systemd/src/basic/process-util.c b/src/systemd/src/basic/process-util.c index 0a4f917cbd..d6ee8b62b8 100644 --- a/src/systemd/src/basic/process-util.c +++ b/src/systemd/src/basic/process-util.c @@ -1108,12 +1108,7 @@ int pid_compare_func(const void *a, const void *b) { const pid_t *p = a, *q = b; /* Suitable for usage in qsort() */ - - if (*p < *q) - return -1; - if (*p > *q) - return 1; - return 0; + return CMP(*p, *q); } int ioprio_parse_priority(const char *s, int *ret) { @@ -1153,7 +1148,7 @@ void reset_cached_pid(void) { /* We use glibc __register_atfork() + __dso_handle directly here, as they are not included in the glibc * headers. __register_atfork() is mostly equivalent to pthread_atfork(), but doesn't require us to link against * libpthread, as it is part of glibc anyway. */ -extern int __register_atfork(void (*prepare) (void), void (*parent) (void), void (*child) (void), void * __dso_handle); +extern int __register_atfork(void (*prepare) (void), void (*parent) (void), void (*child) (void), void *dso_handle); extern void* __dso_handle __attribute__ ((__weak__)); pid_t getpid_cached(void) { diff --git a/src/systemd/src/basic/random-util.c b/src/systemd/src/basic/random-util.c index 91481559db..aa04cc2318 100644 --- a/src/systemd/src/basic/random-util.c +++ b/src/systemd/src/basic/random-util.c @@ -1,5 +1,9 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ +#ifdef __x86_64__ +#include <cpuid.h> +#endif + #include <elf.h> #include <errno.h> #include <fcntl.h> @@ -26,6 +30,41 @@ #include "random-util.h" #include "time-util.h" + +int rdrand64(uint64_t *ret) { + +#ifdef __x86_64__ + static int have_rdrand = -1; + unsigned char err; + + if (have_rdrand < 0) { + uint32_t eax, ebx, ecx, edx; + + /* Check if RDRAND is supported by the CPU */ + if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) == 0) { + have_rdrand = false; + return -EOPNOTSUPP; + } + + have_rdrand = !!(ecx & (1U << 30)); + } + + if (have_rdrand == 0) + return -EOPNOTSUPP; + + asm volatile("rdrand %0;" + "setc %1" + : "=r" (*ret), + "=qm" (err)); + if (!err) + return -EAGAIN; + + return 0; +#else + return -EOPNOTSUPP; +#endif +} + int acquire_random_bytes(void *p, size_t n, bool high_quality_required) { static int have_syscall = -1; @@ -68,8 +107,26 @@ int acquire_random_bytes(void *p, size_t n, bool high_quality_required) { * a best-effort basis. */ have_syscall = true; - if (!high_quality_required) - return -ENODATA; + if (!high_quality_required) { + uint64_t u; + size_t k; + + /* Try x86-64' RDRAND intrinsic if we have it. We only use it if high quality + * randomness is not required, as we don't trust it (who does?). Note that we only do a + * single iteration of RDRAND here, even though the Intel docs suggest calling this in + * a tight loop of 10 invocatins or so. That's because we don't really care about the + * quality here. */ + + if (rdrand64(&u) < 0) + return -ENODATA; + + k = MIN(n, sizeof(u)); + memcpy(p, &u, k); + + /* We only get 64bit out of RDRAND, the rest let's fill up with pseudo-random crap. */ + pseudorandom_bytes((uint8_t*) p + k, n - k); + return 0; + } } else return -errno; } diff --git a/src/systemd/src/basic/random-util.h b/src/systemd/src/basic/random-util.h index 9a103f0e94..affcc9ac1d 100644 --- a/src/systemd/src/basic/random-util.h +++ b/src/systemd/src/basic/random-util.h @@ -21,3 +21,5 @@ static inline uint32_t random_u32(void) { random_bytes(&u, sizeof(u)); return u; } + +int rdrand64(uint64_t *ret); diff --git a/src/systemd/src/basic/socket-util.c b/src/systemd/src/basic/socket-util.c index 69f2c41e9d..986bc6e67f 100644 --- a/src/systemd/src/basic/socket-util.c +++ b/src/systemd/src/basic/socket-util.c @@ -50,7 +50,8 @@ static const char* const socket_address_type_table[] = { DEFINE_STRING_TABLE_LOOKUP(socket_address_type, int); int socket_address_parse(SocketAddress *a, const char *s) { - char *e, *n; + _cleanup_free_ char *n = NULL; + char *e; int r; assert(a); @@ -68,7 +69,9 @@ int socket_address_parse(SocketAddress *a, const char *s) { if (!e) return -EINVAL; - n = strndupa(s+1, e-s-1); + n = strndup(s+1, e-s-1); + if (!n) + return -ENOMEM; errno = 0; if (inet_pton(AF_INET6, n, &a->sockaddr.in6.sin6_addr) <= 0) @@ -125,7 +128,10 @@ int socket_address_parse(SocketAddress *a, const char *s) { if (r < 0) return r; - n = strndupa(cid_start, e - cid_start); + n = strndup(cid_start, e - cid_start); + if (!n) + return -ENOMEM; + if (!isempty(n)) { r = safe_atou(n, &a->sockaddr.vm.svm_cid); if (r < 0) @@ -146,7 +152,9 @@ int socket_address_parse(SocketAddress *a, const char *s) { if (r < 0) return r; - n = strndupa(s, e-s); + n = strndup(s, e-s); + if (!n) + return -ENOMEM; /* IPv4 in w.x.y.z:p notation? */ r = inet_pton(AF_INET, n, &a->sockaddr.in.sin_addr); @@ -1003,9 +1011,10 @@ int getpeergroups(int fd, gid_t **ret) { return (int) n; } -int send_one_fd_sa( +ssize_t send_one_fd_iov_sa( int transport_fd, int fd, + struct iovec *iov, size_t iovlen, const struct sockaddr *sa, socklen_t len, int flags) { @@ -1016,28 +1025,58 @@ int send_one_fd_sa( struct msghdr mh = { .msg_name = (struct sockaddr*) sa, .msg_namelen = len, - .msg_control = &control, - .msg_controllen = sizeof(control), + .msg_iov = iov, + .msg_iovlen = iovlen, }; - struct cmsghdr *cmsg; + ssize_t k; assert(transport_fd >= 0); - assert(fd >= 0); - cmsg = CMSG_FIRSTHDR(&mh); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - memcpy(CMSG_DATA(cmsg), &fd, sizeof(int)); + /* + * We need either an FD or data to send. + * If there's nothing, return an error. + */ + if (fd < 0 && !iov) + return -EINVAL; - mh.msg_controllen = CMSG_SPACE(sizeof(int)); - if (sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags) < 0) - return -errno; + if (fd >= 0) { + struct cmsghdr *cmsg; - return 0; + mh.msg_control = &control; + mh.msg_controllen = sizeof(control); + + cmsg = CMSG_FIRSTHDR(&mh); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + memcpy(CMSG_DATA(cmsg), &fd, sizeof(int)); + + mh.msg_controllen = CMSG_SPACE(sizeof(int)); + } + k = sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags); + if (k < 0) + return (ssize_t) -errno; + + return k; } -int receive_one_fd(int transport_fd, int flags) { +int send_one_fd_sa( + int transport_fd, + int fd, + const struct sockaddr *sa, socklen_t len, + int flags) { + + assert(fd >= 0); + + return (int) send_one_fd_iov_sa(transport_fd, fd, NULL, 0, sa, len, flags); +} + +ssize_t receive_one_fd_iov( + int transport_fd, + struct iovec *iov, size_t iovlen, + int flags, + int *ret_fd) { + union { struct cmsghdr cmsghdr; uint8_t buf[CMSG_SPACE(sizeof(int))]; @@ -1045,10 +1084,14 @@ int receive_one_fd(int transport_fd, int flags) { struct msghdr mh = { .msg_control = &control, .msg_controllen = sizeof(control), + .msg_iov = iov, + .msg_iovlen = iovlen, }; struct cmsghdr *cmsg, *found = NULL; + ssize_t k; assert(transport_fd >= 0); + assert(ret_fd); /* * Receive a single FD via @transport_fd. We don't care for @@ -1058,8 +1101,9 @@ int receive_one_fd(int transport_fd, int flags) { * combination with send_one_fd(). */ - if (recvmsg(transport_fd, &mh, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC | flags) < 0) - return -errno; + k = recvmsg(transport_fd, &mh, MSG_CMSG_CLOEXEC | flags); + if (k < 0) + return (ssize_t) -errno; CMSG_FOREACH(cmsg, &mh) { if (cmsg->cmsg_level == SOL_SOCKET && @@ -1071,12 +1115,33 @@ int receive_one_fd(int transport_fd, int flags) { } } - if (!found) { + if (!found) cmsg_close_all(&mh); + + /* If didn't receive an FD or any data, return an error. */ + if (k == 0 && !found) return -EIO; - } - return *(int*) CMSG_DATA(found); + if (found) + *ret_fd = *(int*) CMSG_DATA(found); + else + *ret_fd = -1; + + return k; +} + +int receive_one_fd(int transport_fd, int flags) { + int fd; + ssize_t k; + + k = receive_one_fd_iov(transport_fd, NULL, 0, flags, &fd); + if (k == 0) + return fd; + + /* k must be negative, since receive_one_fd_iov() only returns + * a positive value if data was received through the iov. */ + assert(k < 0); + return (int) k; } ssize_t next_datagram_size_fd(int fd) { diff --git a/src/systemd/src/basic/socket-util.h b/src/systemd/src/basic/socket-util.h index 8e23cf2dbd..82781a0de1 100644 --- a/src/systemd/src/basic/socket-util.h +++ b/src/systemd/src/basic/socket-util.h @@ -130,11 +130,19 @@ int getpeercred(int fd, struct ucred *ucred); int getpeersec(int fd, char **ret); int getpeergroups(int fd, gid_t **ret); +ssize_t send_one_fd_iov_sa( + int transport_fd, + int fd, + struct iovec *iov, size_t iovlen, + const struct sockaddr *sa, socklen_t len, + int flags); int send_one_fd_sa(int transport_fd, int fd, const struct sockaddr *sa, socklen_t len, int flags); -#define send_one_fd(transport_fd, fd, flags) send_one_fd_sa(transport_fd, fd, NULL, 0, flags) +#define send_one_fd_iov(transport_fd, fd, iov, iovlen, flags) send_one_fd_iov_sa(transport_fd, fd, iov, iovlen, NULL, 0, flags) +#define send_one_fd(transport_fd, fd, flags) send_one_fd_iov_sa(transport_fd, fd, NULL, 0, NULL, 0, flags) +ssize_t receive_one_fd_iov(int transport_fd, struct iovec *iov, size_t iovlen, int flags, int *ret_fd); int receive_one_fd(int transport_fd, int flags); ssize_t next_datagram_size_fd(int fd); diff --git a/src/systemd/src/basic/stat-util.c b/src/systemd/src/basic/stat-util.c index 07154e25bb..762777e94f 100644 --- a/src/systemd/src/basic/stat-util.c +++ b/src/systemd/src/basic/stat-util.c @@ -45,6 +45,17 @@ int is_dir(const char* path, bool follow) { return !!S_ISDIR(st.st_mode); } +int is_dir_fd(int fd) { + struct stat st; + int r; + + r = fstat(fd, &st); + if (r < 0) + return -errno; + + return !!S_ISDIR(st.st_mode); +} + int is_device_node(const char *path) { struct stat info; diff --git a/src/systemd/src/basic/stat-util.h b/src/systemd/src/basic/stat-util.h index f8014ed30b..1a725f1da0 100644 --- a/src/systemd/src/basic/stat-util.h +++ b/src/systemd/src/basic/stat-util.h @@ -12,6 +12,7 @@ int is_symlink(const char *path); int is_dir(const char *path, bool follow); +int is_dir_fd(int fd); int is_device_node(const char *path); int dir_is_empty(const char *path); diff --git a/src/systemd/src/basic/strv.c b/src/systemd/src/basic/strv.c index b3716233b5..abf3fc4c7b 100644 --- a/src/systemd/src/basic/strv.c +++ b/src/systemd/src/basic/strv.c @@ -253,6 +253,10 @@ char **strv_split(const char *s, const char *separator) { assert(s); + s += strspn(s, separator); + if (isempty(s)) + return new0(char*, 1); + n = 0; FOREACH_WORD_SEPARATOR(word, l, s, separator, state) n++; diff --git a/src/systemd/src/basic/time-util.c b/src/systemd/src/basic/time-util.c index fe201c398d..81d3f3f38f 100644 --- a/src/systemd/src/basic/time-util.c +++ b/src/systemd/src/basic/time-util.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ +#include <ctype.h> #include <errno.h> #include <limits.h> #include <stdlib.h> @@ -996,10 +997,10 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) { } for (;;) { + usec_t multiplier = default_unit, k; long long l, z = 0; - char *e; unsigned n = 0; - usec_t multiplier = default_unit, k; + char *e; p += strspn(p, WHITESPACE); @@ -1010,6 +1011,9 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) { break; } + if (*p == '-') /* Don't allow "-0" */ + return -ERANGE; + errno = 0; l = strtoll(p, &e, 10); if (errno > 0) @@ -1020,14 +1024,16 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) { if (*e == '.') { char *b = e + 1; + /* Don't allow "0.-0", "3.+1" or "3. 1" */ + if (*b == '-' || *b == '+' || isspace(*b)) + return -EINVAL; + errno = 0; z = strtoll(b, &e, 10); if (errno > 0) return -errno; - if (z < 0) return -ERANGE; - if (e == b) return -EINVAL; @@ -1144,26 +1150,28 @@ int parse_nsec(const char *t, nsec_t *nsec) { break; } + if (*p == '-') + return -ERANGE; + errno = 0; l = strtoll(p, &e, 10); - if (errno > 0) return -errno; - if (l < 0) return -ERANGE; if (*e == '.') { char *b = e + 1; + if (*b == '-' || *b == '+' || isspace(*b)) + return -EINVAL; + errno = 0; z = strtoll(b, &e, 10); if (errno > 0) return -errno; - if (z < 0) return -ERANGE; - if (e == b) return -EINVAL; diff --git a/src/systemd/src/basic/utf8.c b/src/systemd/src/basic/utf8.c index 531b518fad..a5ce1a2944 100644 --- a/src/systemd/src/basic/utf8.c +++ b/src/systemd/src/basic/utf8.c @@ -1,7 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - Copyright © 2008-2011 Kay Sievers -***/ /* Parts of this file are based on the GLIB utf8 validation functions. The * original license text follows. */ diff --git a/src/systemd/src/basic/util.c b/src/systemd/src/basic/util.c index 8f2d6061da..f951d641d7 100644 --- a/src/systemd/src/basic/util.c +++ b/src/systemd/src/basic/util.c @@ -77,31 +77,6 @@ bool display_is_local(const char *display) { display[1] <= '9'; } -int socket_from_display(const char *display, char **path) { - size_t k; - char *f, *c; - - assert(display); - assert(path); - - if (!display_is_local(display)) - return -EINVAL; - - k = strspn(display+1, "0123456789"); - - f = new(char, STRLEN("/tmp/.X11-unix/X") + k + 1); - if (!f) - return -ENOMEM; - - c = stpcpy(f, "/tmp/.X11-unix/X"); - memcpy(c, display+1, k); - c[k] = 0; - - *path = f; - - return 0; -} - bool kexec_loaded(void) { _cleanup_free_ char *s = NULL; @@ -255,6 +230,11 @@ int container_get_leader(const char *machine, pid_t *pid) { assert(machine); assert(pid); + if (streq(machine, ".host")) { + *pid = 1; + return 0; + } + if (!machine_name_is_valid(machine)) return -EINVAL; diff --git a/src/systemd/src/basic/util.h b/src/systemd/src/basic/util.h index 9699d228f9..308933ac90 100644 --- a/src/systemd/src/basic/util.h +++ b/src/systemd/src/basic/util.h @@ -50,7 +50,6 @@ static inline const char* enable_disable(bool b) { bool plymouth_running(void); bool display_is_local(const char *display) _pure_; -int socket_from_display(const char *display, char **path); #define NULSTR_FOREACH(i, l) \ for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1) @@ -113,9 +112,7 @@ static inline void qsort_r_safe(void *base, size_t nmemb, size_t size, int (*com qsort_r(base, nmemb, size, compar, userdata); } -/** - * Normal memcpy requires src to be nonnull. We do nothing if n is 0. - */ +/* Normal memcpy requires src to be nonnull. We do nothing if n is 0. */ static inline void memcpy_safe(void *dst, const void *src, size_t n) { if (n == 0) return; @@ -123,6 +120,15 @@ static inline void memcpy_safe(void *dst, const void *src, size_t n) { memcpy(dst, src, n); } +/* Normal memcmp requires s1 and s2 to be nonnull. We do nothing if n is 0. */ +static inline int memcmp_safe(const void *s1, const void *s2, size_t n) { + if (n == 0) + return 0; + assert(s1); + assert(s2); + return memcmp(s1, s2, n); +} + int on_ac_power(void); #define memzero(x,l) (memset((x), 0, (l))) diff --git a/src/systemd/src/libsystemd-network/arp-util.c b/src/systemd/src/libsystemd-network/arp-util.c index 0e0c234990..3a86f3f077 100644 --- a/src/systemd/src/libsystemd-network/arp-util.c +++ b/src/systemd/src/libsystemd-network/arp-util.c @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ /*** Copyright © 2014 Axis Communications AB. All rights reserved. - Copyright © 2015 Tom Gundersen ***/ #include <linux/filter.h> diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.c b/src/systemd/src/libsystemd-network/dhcp-identifier.c index ebbfe8bcd2..531cf6783b 100644 --- a/src/systemd/src/libsystemd-network/dhcp-identifier.c +++ b/src/systemd/src/libsystemd-network/dhcp-identifier.c @@ -1,9 +1,9 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - Copyright © 2015 Tom Gundersen <teg@jklmen> -***/ -#include "libudev.h" +#include <linux/if_infiniband.h> +#include <net/if_arp.h> + +#include "sd-device.h" #include "sd-id128.h" #include "dhcp-identifier.h" @@ -11,11 +11,12 @@ #include "network-internal.h" #include "siphash24.h" #include "sparse-endian.h" -#include "udev-util.h" #include "virt.h" -#define SYSTEMD_PEN 43793 -#define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09) +#define SYSTEMD_PEN 43793 +#define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09) +#define APPLICATION_ID SD_ID128_MAKE(a5,0a,d1,12,bf,60,45,77,a2,fb,74,1a,b1,95,5b,03) +#define USEC_2000 ((usec_t) 946684800000000) /* 2000-01-01 00:00:00 UTC */ int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) { struct duid d; @@ -48,6 +49,56 @@ int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) { return 0; } +int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len) { + uint16_t time_from_2000y; + + assert(duid); + assert(len); + assert(addr); + + if (arp_type == ARPHRD_ETHER) + assert_return(addr_len == ETH_ALEN, -EINVAL); + else if (arp_type == ARPHRD_INFINIBAND) + assert_return(addr_len == INFINIBAND_ALEN, -EINVAL); + else + return -EINVAL; + + if (t < USEC_2000) + time_from_2000y = 0; + else + time_from_2000y = (uint16_t) (((t - USEC_2000) / USEC_PER_SEC) & 0xffffffff); + + unaligned_write_be16(&duid->type, DUID_TYPE_LLT); + unaligned_write_be16(&duid->llt.htype, arp_type); + unaligned_write_be32(&duid->llt.time, time_from_2000y); + memcpy(duid->llt.haddr, addr, addr_len); + + *len = sizeof(duid->type) + sizeof(duid->llt.htype) + sizeof(duid->llt.time) + addr_len; + + return 0; +} + +int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len) { + assert(duid); + assert(len); + assert(addr); + + if (arp_type == ARPHRD_ETHER) + assert_return(addr_len == ETH_ALEN, -EINVAL); + else if (arp_type == ARPHRD_INFINIBAND) + assert_return(addr_len == INFINIBAND_ALEN, -EINVAL); + else + return -EINVAL; + + unaligned_write_be16(&duid->type, DUID_TYPE_LL); + unaligned_write_be16(&duid->ll.htype, arp_type); + memcpy(duid->ll.haddr, addr, addr_len); + + *len = sizeof(duid->type) + sizeof(duid->ll.htype) + addr_len; + + return 0; +} + int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) { sd_id128_t machine_id; uint64_t hash; @@ -66,33 +117,50 @@ int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) { *len = sizeof(duid->type) + sizeof(duid->en); /* a bit of snake-oil perhaps, but no need to expose the machine-id - directly; duid->en.id might not be aligned, so we need to copy */ + * directly; duid->en.id might not be aligned, so we need to copy */ hash = htole64(siphash24(&machine_id, sizeof(machine_id), HASH_KEY.bytes)); memcpy(duid->en.id, &hash, sizeof(duid->en.id)); return 0; } +int dhcp_identifier_set_duid_uuid(struct duid *duid, size_t *len) { + sd_id128_t machine_id; + int r; + + assert(duid); + assert(len); + + r = sd_id128_get_machine_app_specific(APPLICATION_ID, &machine_id); + if (r < 0) + return r; + + unaligned_write_be16(&duid->type, DUID_TYPE_UUID); + memcpy(&duid->raw.data, &machine_id, sizeof(machine_id)); + + *len = sizeof(duid->type) + sizeof(machine_id); + + return 0; +} + int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id) { - /* name is a pointer to memory in the udev_device struct, so must - have the same scope */ - _cleanup_(udev_device_unrefp) struct udev_device *device = NULL; + /* name is a pointer to memory in the sd_device struct, so must + * have the same scope */ + _cleanup_(sd_device_unrefp) sd_device *device = NULL; const char *name = NULL; uint64_t id; if (detect_container() <= 0) { /* not in a container, udev will be around */ - _cleanup_(udev_unrefp) struct udev *udev; char ifindex_str[2 + DECIMAL_STR_MAX(int)]; - - udev = udev_new(); - if (!udev) - return -ENOMEM; + int initialized, r; sprintf(ifindex_str, "n%d", ifindex); - device = udev_device_new_from_device_id(udev, ifindex_str); - if (device) { - if (udev_device_get_is_initialized(device) <= 0) + if (sd_device_new_from_device_id(&device, ifindex_str) >= 0) { + r = sd_device_get_is_initialized(device, &initialized); + if (r < 0) + return r; + if (!initialized) /* not yet ready */ return -EBUSY; diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.h b/src/systemd/src/libsystemd-network/dhcp-identifier.h index 42d4956d10..64315d3a3b 100644 --- a/src/systemd/src/libsystemd-network/dhcp-identifier.h +++ b/src/systemd/src/libsystemd-network/dhcp-identifier.h @@ -1,14 +1,11 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - Copyright © 2015 Tom Gundersen <teg@jklmen> -***/ - #include "sd-id128.h" #include "macro.h" #include "sparse-endian.h" +#include "time-util.h" #include "unaligned.h" typedef enum DUIDType { @@ -31,18 +28,18 @@ struct duid { union { struct { /* DUID_TYPE_LLT */ - uint16_t htype; - uint32_t time; + be16_t htype; + be32_t time; uint8_t haddr[0]; } _packed_ llt; struct { /* DUID_TYPE_EN */ - uint32_t pen; + be32_t pen; uint8_t id[8]; } _packed_ en; struct { /* DUID_TYPE_LL */ - int16_t htype; + be16_t htype; uint8_t haddr[0]; } _packed_ ll; struct { @@ -56,5 +53,8 @@ struct duid { } _packed_; int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len); +int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len); +int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len); int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len); +int dhcp_identifier_set_duid_uuid(struct duid *duid, size_t *len); int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id); diff --git a/src/systemd/src/libsystemd-network/dhcp-internal.h b/src/systemd/src/libsystemd-network/dhcp-internal.h index 257a3c2e2f..a0f9c2299f 100644 --- a/src/systemd/src/libsystemd-network/dhcp-internal.h +++ b/src/systemd/src/libsystemd-network/dhcp-internal.h @@ -3,7 +3,6 @@ /*** Copyright © 2013 Intel Corporation. All rights reserved. - Copyright © 2014 Tom Gundersen ***/ #include <linux/if_packet.h> diff --git a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h index fabac183ef..9d245a9059 100644 --- a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h +++ b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h @@ -3,7 +3,6 @@ /*** Copyright © 2013 Intel Corporation. All rights reserved. - Copyright © 2014 Tom Gundersen ***/ #include <stdint.h> diff --git a/src/systemd/src/libsystemd-network/dhcp-packet.c b/src/systemd/src/libsystemd-network/dhcp-packet.c index 79707933eb..d29cd06cb1 100644 --- a/src/systemd/src/libsystemd-network/dhcp-packet.c +++ b/src/systemd/src/libsystemd-network/dhcp-packet.c @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ /*** Copyright © 2013 Intel Corporation. All rights reserved. - Copyright © 2014 Tom Gundersen ***/ #include <errno.h> diff --git a/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h b/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h index dc85c437c9..ff0b0f00ce 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h +++ b/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h @@ -2,7 +2,6 @@ #pragma once /*** - Copyright © 2014 Tom Gundersen Copyright © 2014-2015 Intel Corporation. All rights reserved. ***/ diff --git a/src/systemd/src/libsystemd-network/lldp-internal.h b/src/systemd/src/libsystemd-network/lldp-internal.h index e56509884e..328d51f8ea 100644 --- a/src/systemd/src/libsystemd-network/lldp-internal.h +++ b/src/systemd/src/libsystemd-network/lldp-internal.h @@ -1,11 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - Copyright © 2014 Tom Gundersen - Copyright © 2014 Susant Sahani -***/ - #include "sd-event.h" #include "sd-lldp.h" diff --git a/src/systemd/src/libsystemd-network/lldp-neighbor.c b/src/systemd/src/libsystemd-network/lldp-neighbor.c index 5dcb051373..8295d4d404 100644 --- a/src/systemd/src/libsystemd-network/lldp-neighbor.c +++ b/src/systemd/src/libsystemd-network/lldp-neighbor.c @@ -26,22 +26,15 @@ static int lldp_neighbor_id_compare_func(const void *a, const void *b) { if (r != 0) return r; - if (x->chassis_id_size < y->chassis_id_size) - return -1; - - if (x->chassis_id_size > y->chassis_id_size) - return 1; + r = CMP(x->chassis_id_size, y->chassis_id_size); + if (r != 0) + return r; r = memcmp(x->port_id, y->port_id, MIN(x->port_id_size, y->port_id_size)); if (r != 0) return r; - if (x->port_id_size < y->port_id_size) - return -1; - if (x->port_id_size > y->port_id_size) - return 1; - - return 0; + return CMP(x->port_id_size, y->port_id_size); } const struct hash_ops lldp_neighbor_id_hash_ops = { @@ -52,13 +45,7 @@ const struct hash_ops lldp_neighbor_id_hash_ops = { int lldp_neighbor_prioq_compare_func(const void *a, const void *b) { const sd_lldp_neighbor *x = a, *y = b; - if (x->until < y->until) - return -1; - - if (x->until > y->until) - return 1; - - return 0; + return CMP(x->until, y->until); } _public_ sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n) { diff --git a/src/systemd/src/libsystemd-network/lldp-network.c b/src/systemd/src/libsystemd-network/lldp-network.c index 63ba718f46..a4020d1e19 100644 --- a/src/systemd/src/libsystemd-network/lldp-network.c +++ b/src/systemd/src/libsystemd-network/lldp-network.c @@ -1,8 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - Copyright © 2014 Tom Gundersen - Copyright © 2014 Susant Sahani -***/ #include <linux/filter.h> #include <netinet/if_ether.h> diff --git a/src/systemd/src/libsystemd-network/lldp-network.h b/src/systemd/src/libsystemd-network/lldp-network.h index 1d773acc2d..e4ed2898a5 100644 --- a/src/systemd/src/libsystemd-network/lldp-network.h +++ b/src/systemd/src/libsystemd-network/lldp-network.h @@ -1,11 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - Copyright © 2014 Tom Gundersen - Copyright © 2014 Susant Sahani -***/ - #include "sd-event.h" int lldp_network_bind_raw_socket(int ifindex); diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c index adb92d1c95..949798a1d3 100644 --- a/src/systemd/src/libsystemd-network/network-internal.c +++ b/src/systemd/src/libsystemd-network/network-internal.c @@ -1,7 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - Copyright © 2013 Tom Gundersen <teg@jklm.no> -***/ #include <arpa/inet.h> #include <linux/if.h> @@ -26,24 +23,22 @@ #include "utf8.h" #include "util.h" -const char *net_get_name(struct udev_device *device) { +const char *net_get_name(sd_device *device) { const char *name, *field; assert(device); /* fetch some persistent data unique (on this machine) to this device */ - FOREACH_STRING(field, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC") { - name = udev_device_get_property_value(device, field); - if (name) + FOREACH_STRING(field, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC") + if (sd_device_get_property_value(device, field, &name) >= 0) return name; - } return NULL; } #define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a) -int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result) { +int net_get_unique_predictable_data(sd_device *device, uint64_t *result) { size_t l, sz = 0; const char *name = NULL; int r; @@ -127,7 +122,7 @@ bool net_match_config(Set *match_mac, if (match_arch && condition_test(match_arch) <= 0) return false; - if (match_mac && dev_mac && !set_contains(match_mac, dev_mac)) + if (match_mac && (!dev_mac || !set_contains(match_mac, dev_mac))) return false; if (!net_condition_test_strv(match_paths, dev_path)) diff --git a/src/systemd/src/libsystemd-network/network-internal.h b/src/systemd/src/libsystemd-network/network-internal.h index 51b69c3d15..45020c2bcf 100644 --- a/src/systemd/src/libsystemd-network/network-internal.h +++ b/src/systemd/src/libsystemd-network/network-internal.h @@ -1,18 +1,14 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - Copyright © 2013 Tom Gundersen <teg@jklm.no> -***/ - #include <stdbool.h> +#include "sd-device.h" #include "sd-dhcp-lease.h" #include "condition.h" #include "conf-parser.h" #include "set.h" -#include "udev.h" #define LINK_BRIDGE_PORT_PRIORITY_INVALID 128 #define LINK_BRIDGE_PORT_PRIORITY_MAX 63 @@ -42,8 +38,8 @@ CONFIG_PARSER_PROTOTYPE(config_parse_ifalias); CONFIG_PARSER_PROTOTYPE(config_parse_iaid); CONFIG_PARSER_PROTOTYPE(config_parse_bridge_port_priority); -int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result); -const char *net_get_name(struct udev_device *device); +int net_get_unique_predictable_data(sd_device *device, uint64_t *result); +const char *net_get_name(sd_device *device); void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size); int deserialize_in_addrs(struct in_addr **addresses, 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 ff434f8ce7..de86028a5d 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c @@ -341,13 +341,14 @@ int sd_dhcp_client_set_client_id( * without further modification. Otherwise, if duid_type is supported, DUID * is set based on that type. Otherwise, an error is returned. */ -static int dhcp_client_set_iaid_duid( +static int dhcp_client_set_iaid_duid_internal( sd_dhcp_client *client, uint32_t iaid, bool append_iaid, uint16_t duid_type, const void *duid, - size_t duid_len) { + size_t duid_len, + usec_t llt_time) { DHCP_CLIENT_DONT_DESTROY(client); int r; @@ -381,18 +382,43 @@ static int dhcp_client_set_iaid_duid( client->client_id.ns.duid.type = htobe16(duid_type); memcpy(&client->client_id.ns.duid.raw.data, duid, duid_len); len = sizeof(client->client_id.ns.duid.type) + duid_len; - } else if (duid_type == DUID_TYPE_EN) { - r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &len); - if (r < 0) - return r; } else - return -EOPNOTSUPP; + switch (duid_type) { + case DUID_TYPE_LLT: + if (!client->mac_addr || client->mac_addr_len == 0) + return -EOPNOTSUPP; + + r = dhcp_identifier_set_duid_llt(&client->client_id.ns.duid, llt_time, client->mac_addr, client->mac_addr_len, client->arp_type, &len); + if (r < 0) + return r; + break; + case DUID_TYPE_EN: + r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &len); + if (r < 0) + return r; + break; + case DUID_TYPE_LL: + if (!client->mac_addr || client->mac_addr_len == 0) + return -EOPNOTSUPP; + + r = dhcp_identifier_set_duid_ll(&client->client_id.ns.duid, client->mac_addr, client->mac_addr_len, client->arp_type, &len); + if (r < 0) + return r; + break; + case DUID_TYPE_UUID: + r = dhcp_identifier_set_duid_uuid(&client->client_id.ns.duid, &len); + if (r < 0) + return r; + break; + default: + return -EINVAL; + } client->client_id_len = sizeof(client->client_id.type) + len + (append_iaid ? sizeof(client->client_id.ns.iaid) : 0); if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) { - log_dhcp_client(client, "Configured IAID+DUID, restarting."); + log_dhcp_client(client, "Configured %sDUID, restarting.", append_iaid ? "IAID+" : ""); client_stop(client, SD_DHCP_CLIENT_EVENT_STOP); sd_dhcp_client_start(client); } @@ -406,7 +432,14 @@ int sd_dhcp_client_set_iaid_duid( uint16_t duid_type, const void *duid, size_t duid_len) { - return dhcp_client_set_iaid_duid(client, iaid, true, duid_type, duid, duid_len); + return dhcp_client_set_iaid_duid_internal(client, iaid, true, duid_type, duid, duid_len, 0); +} + +int sd_dhcp_client_set_iaid_duid_llt( + sd_dhcp_client *client, + uint32_t iaid, + usec_t llt_time) { + return dhcp_client_set_iaid_duid_internal(client, iaid, true, DUID_TYPE_LLT, NULL, 0, llt_time); } int sd_dhcp_client_set_duid( @@ -414,7 +447,13 @@ int sd_dhcp_client_set_duid( uint16_t duid_type, const void *duid, size_t duid_len) { - return dhcp_client_set_iaid_duid(client, 0, false, duid_type, duid, duid_len); + return dhcp_client_set_iaid_duid_internal(client, 0, false, duid_type, duid, duid_len, 0); +} + +int sd_dhcp_client_set_duid_llt( + sd_dhcp_client *client, + usec_t llt_time) { + return dhcp_client_set_iaid_duid_internal(client, 0, false, DUID_TYPE_LLT, NULL, 0, llt_time); } int sd_dhcp_client_set_hostname( diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c index 47cd439e26..8b6f5ad34f 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ /*** Copyright © 2013 Intel Corporation. All rights reserved. - Copyright © 2014 Tom Gundersen ***/ #include <arpa/inet.h> @@ -26,6 +25,7 @@ #include "parse-util.h" #include "stdio-util.h" #include "string-util.h" +#include "strv.h" #include "unaligned.h" int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) { diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c index b3bc259280..84c58af346 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c @@ -182,13 +182,14 @@ static int client_ensure_duid(sd_dhcp6_client *client) { * without further modification. Otherwise, if duid_type is supported, DUID * is set based on that type. Otherwise, an error is returned. */ -int sd_dhcp6_client_set_duid( +static int dhcp6_client_set_duid_internal( sd_dhcp6_client *client, uint16_t duid_type, const void *duid, - size_t duid_len) { - + size_t duid_len, + usec_t llt_time) { int r; + assert_return(client, -EINVAL); assert_return(duid_len == 0 || duid != NULL, -EINVAL); assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); @@ -197,22 +198,59 @@ int sd_dhcp6_client_set_duid( r = dhcp_validate_duid_len(duid_type, duid_len); if (r < 0) return r; - } - if (duid != NULL) { client->duid.type = htobe16(duid_type); memcpy(&client->duid.raw.data, duid, duid_len); client->duid_len = sizeof(client->duid.type) + duid_len; - } else if (duid_type == DUID_TYPE_EN) { - r = dhcp_identifier_set_duid_en(&client->duid, &client->duid_len); - if (r < 0) - return r; } else - return -EOPNOTSUPP; + switch (duid_type) { + case DUID_TYPE_LLT: + if (!client->mac_addr || client->mac_addr_len == 0) + return -EOPNOTSUPP; + + r = dhcp_identifier_set_duid_llt(&client->duid, 0, client->mac_addr, client->mac_addr_len, client->arp_type, &client->duid_len); + if (r < 0) + return r; + break; + case DUID_TYPE_EN: + r = dhcp_identifier_set_duid_en(&client->duid, &client->duid_len); + if (r < 0) + return r; + break; + case DUID_TYPE_LL: + if (!client->mac_addr || client->mac_addr_len == 0) + return -EOPNOTSUPP; + + r = dhcp_identifier_set_duid_ll(&client->duid, client->mac_addr, client->mac_addr_len, client->arp_type, &client->duid_len); + if (r < 0) + return r; + break; + case DUID_TYPE_UUID: + r = dhcp_identifier_set_duid_uuid(&client->duid, &client->duid_len); + if (r < 0) + return r; + break; + default: + return -EINVAL; + } return 0; } +int sd_dhcp6_client_set_duid( + sd_dhcp6_client *client, + uint16_t duid_type, + const void *duid, + size_t duid_len) { + return dhcp6_client_set_duid_internal(client, duid_type, duid, duid_len, 0); +} + +int sd_dhcp6_client_set_duid_llt( + sd_dhcp6_client *client, + usec_t llt_time) { + return dhcp6_client_set_duid_internal(client, DUID_TYPE_LLT, NULL, 0, llt_time); +} + int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid) { assert_return(client, -EINVAL); assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); @@ -1144,9 +1182,8 @@ static int client_receive_message( return 0; } - if (r >= 0) - log_dhcp6_client(client, "Recv %s", - dhcp6_message_type_to_string(message->type)); + log_dhcp6_client(client, "Recv %s", + dhcp6_message_type_to_string(message->type)); return 0; } diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c index 4a4e37a100..779ad54b4a 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c @@ -1,6 +1,5 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ /*** - Copyright © 2014 Tom Gundersen Copyright © 2014-2015 Intel Corporation. All rights reserved. ***/ diff --git a/src/systemd/src/libsystemd-network/sd-ipv4acd.c b/src/systemd/src/libsystemd-network/sd-ipv4acd.c index 8cd685b04d..a40d40db90 100644 --- a/src/systemd/src/libsystemd-network/sd-ipv4acd.c +++ b/src/systemd/src/libsystemd-network/sd-ipv4acd.c @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ /*** Copyright © 2014 Axis Communications AB. All rights reserved. - Copyright © 2015 Tom Gundersen ***/ #include <arpa/inet.h> diff --git a/src/systemd/src/libsystemd-network/sd-ipv4ll.c b/src/systemd/src/libsystemd-network/sd-ipv4ll.c index 001b322610..7307e1668f 100644 --- a/src/systemd/src/libsystemd-network/sd-ipv4ll.c +++ b/src/systemd/src/libsystemd-network/sd-ipv4ll.c @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ /*** Copyright © 2014 Axis Communications AB. All rights reserved. - Copyright © 2015 Tom Gundersen ***/ #include <arpa/inet.h> diff --git a/src/systemd/src/libsystemd-network/sd-lldp.c b/src/systemd/src/libsystemd-network/sd-lldp.c index 15a7f291e4..c75d6079e1 100644 --- a/src/systemd/src/libsystemd-network/sd-lldp.c +++ b/src/systemd/src/libsystemd-network/sd-lldp.c @@ -1,8 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - Copyright © 2014 Tom Gundersen - Copyright © 2014 Susant Sahani -***/ #include <arpa/inet.h> #include <linux/sockios.h> diff --git a/src/systemd/src/libsystemd/sd-event/sd-event.c b/src/systemd/src/libsystemd/sd-event/sd-event.c index d53b9a7026..6e50fcc4c6 100644 --- a/src/systemd/src/libsystemd/sd-event/sd-event.c +++ b/src/systemd/src/libsystemd/sd-event/sd-event.c @@ -1,6 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** -***/ #include <sys/epoll.h> #include <sys/timerfd.h> @@ -92,7 +90,7 @@ struct sd_event_source { char *description; EventSourceType type:5; - int enabled:3; + signed int enabled:3; bool pending:1; bool dispatching:1; bool floating:1; diff --git a/src/systemd/src/libsystemd/sd-id128/id128-util.c b/src/systemd/src/libsystemd/sd-id128/id128-util.c index edee985e44..95c9e1138c 100644 --- a/src/systemd/src/libsystemd/sd-id128/id128-util.c +++ b/src/systemd/src/libsystemd/sd-id128/id128-util.c @@ -1,6 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** -***/ #include <errno.h> #include <fcntl.h> diff --git a/src/systemd/src/libsystemd/sd-id128/id128-util.h b/src/systemd/src/libsystemd/sd-id128/id128-util.h index f0b4eca581..44f159c0b6 100644 --- a/src/systemd/src/libsystemd/sd-id128/id128-util.h +++ b/src/systemd/src/libsystemd/sd-id128/id128-util.h @@ -1,9 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** -***/ - #include <stdbool.h> #include "sd-id128.h" diff --git a/src/systemd/src/libsystemd/sd-id128/sd-id128.c b/src/systemd/src/libsystemd/sd-id128/sd-id128.c index b7123280f3..9d93732d7e 100644 --- a/src/systemd/src/libsystemd/sd-id128/sd-id128.c +++ b/src/systemd/src/libsystemd/sd-id128/sd-id128.c @@ -1,6 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** -***/ #include <errno.h> #include <fcntl.h> diff --git a/src/systemd/src/shared/dns-domain.c b/src/systemd/src/shared/dns-domain.c index de2fcca8b2..1ecfb77de2 100644 --- a/src/systemd/src/shared/dns-domain.c +++ b/src/systemd/src/shared/dns-domain.c @@ -1,6 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - ***/ #if HAVE_LIBIDN2 # include <idn2.h> @@ -505,7 +503,7 @@ int dns_name_compare_func(const void *a, const void *b) { r = dns_label_unescape_suffix(a, &x, la, sizeof(la)); q = dns_label_unescape_suffix(b, &y, lb, sizeof(lb)); if (r < 0 || q < 0) - return r - q; + return CMP(r, q); r = ascii_strcasecmp_nn(la, r, lb, q); if (r != 0) diff --git a/src/systemd/src/shared/dns-domain.h b/src/systemd/src/shared/dns-domain.h index 0fd72cb029..1e9b57059b 100644 --- a/src/systemd/src/shared/dns-domain.h +++ b/src/systemd/src/shared/dns-domain.h @@ -1,9 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - ***/ - #include <errno.h> #include <stdbool.h> #include <stddef.h> diff --git a/src/systemd/src/systemd/_sd-common.h b/src/systemd/src/systemd/_sd-common.h index 7b54d179eb..4742b2e742 100644 --- a/src/systemd/src/systemd/_sd-common.h +++ b/src/systemd/src/systemd/_sd-common.h @@ -3,7 +3,6 @@ #define foosdcommonhfoo /*** - systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or diff --git a/src/systemd/src/systemd/sd-dhcp-client.h b/src/systemd/src/systemd/sd-dhcp-client.h index 931b0e890b..e388552064 100644 --- a/src/systemd/src/systemd/sd-dhcp-client.h +++ b/src/systemd/src/systemd/sd-dhcp-client.h @@ -131,11 +131,18 @@ int sd_dhcp_client_set_iaid_duid( uint16_t duid_type, const void *duid, size_t duid_len); +int sd_dhcp_client_set_iaid_duid_llt( + sd_dhcp_client *client, + uint32_t iaid, + uint64_t llt_time); int sd_dhcp_client_set_duid( sd_dhcp_client *client, uint16_t duid_type, const void *duid, size_t duid_len); +int sd_dhcp_client_set_duid_llt( + sd_dhcp_client *client, + uint64_t llt_time); int sd_dhcp_client_get_client_id( sd_dhcp_client *client, uint8_t *type, diff --git a/src/systemd/src/systemd/sd-dhcp-lease.h b/src/systemd/src/systemd/sd-dhcp-lease.h index 16c05661ec..2a60145f5b 100644 --- a/src/systemd/src/systemd/sd-dhcp-lease.h +++ b/src/systemd/src/systemd/sd-dhcp-lease.h @@ -4,8 +4,6 @@ /*** Copyright © 2013 Intel Corporation. All rights reserved. - Copyright © 2014 Tom Gundersen - systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or diff --git a/src/systemd/src/systemd/sd-dhcp6-client.h b/src/systemd/src/systemd/sd-dhcp6-client.h index 4f3b2d9e2e..fa36dca909 100644 --- a/src/systemd/src/systemd/sd-dhcp6-client.h +++ b/src/systemd/src/systemd/sd-dhcp6-client.h @@ -102,6 +102,9 @@ int sd_dhcp6_client_set_duid( uint16_t duid_type, const void *duid, size_t duid_len); +int sd_dhcp6_client_set_duid_llt( + sd_dhcp6_client *client, + uint64_t llt_time); int sd_dhcp6_client_set_iaid( sd_dhcp6_client *client, uint32_t iaid); diff --git a/src/systemd/src/systemd/sd-dhcp6-lease.h b/src/systemd/src/systemd/sd-dhcp6-lease.h index a673de5edd..33a32a6dc5 100644 --- a/src/systemd/src/systemd/sd-dhcp6-lease.h +++ b/src/systemd/src/systemd/sd-dhcp6-lease.h @@ -3,7 +3,6 @@ #define foosddhcp6leasehfoo /*** - Copyright © 2014 Tom Gundersen Copyright © 2014-2015 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it diff --git a/src/systemd/src/systemd/sd-event.h b/src/systemd/src/systemd/sd-event.h index 7fcae4ac49..eb35b83431 100644 --- a/src/systemd/src/systemd/sd-event.h +++ b/src/systemd/src/systemd/sd-event.h @@ -3,7 +3,6 @@ #define foosdeventhfoo /*** - systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or diff --git a/src/systemd/src/systemd/sd-id128.h b/src/systemd/src/systemd/sd-id128.h index b24fd06f01..143a0ffb5e 100644 --- a/src/systemd/src/systemd/sd-id128.h +++ b/src/systemd/src/systemd/sd-id128.h @@ -3,7 +3,6 @@ #define foosdid128hfoo /*** - systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or diff --git a/src/systemd/src/systemd/sd-ipv4acd.h b/src/systemd/src/systemd/sd-ipv4acd.h index 259db26330..039ed3c7f2 100644 --- a/src/systemd/src/systemd/sd-ipv4acd.h +++ b/src/systemd/src/systemd/sd-ipv4acd.h @@ -4,8 +4,6 @@ /*** Copyright © 2014 Axis Communications AB. All rights reserved. - Copyright © 2015 Tom Gundersen - systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or diff --git a/src/systemd/src/systemd/sd-lldp.h b/src/systemd/src/systemd/sd-lldp.h index 11a2119ab6..d650794cc0 100644 --- a/src/systemd/src/systemd/sd-lldp.h +++ b/src/systemd/src/systemd/sd-lldp.h @@ -3,9 +3,6 @@ #define foosdlldphfoo /*** - Copyright © 2014 Tom Gundersen - Copyright © 2014 Susant Sahani - systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or |