systemd: merge branch systemd into master

https://github.com/NetworkManager/NetworkManager/pull/186
This commit is contained in:
Thomas Haller
2018-08-26 19:33:40 +02:00
74 changed files with 1517 additions and 355 deletions

View File

@@ -1374,14 +1374,12 @@ src_libsystemd_nm_la_SOURCES = \
src/systemd/sd-adapt/def.h \ src/systemd/sd-adapt/def.h \
src/systemd/sd-adapt/device-nodes.h \ src/systemd/sd-adapt/device-nodes.h \
src/systemd/sd-adapt/dirent-util.h \ src/systemd/sd-adapt/dirent-util.h \
src/systemd/sd-adapt/env-util.h \
src/systemd/sd-adapt/errno-list.h \ src/systemd/sd-adapt/errno-list.h \
src/systemd/sd-adapt/format-util.h \ src/systemd/sd-adapt/format-util.h \
src/systemd/sd-adapt/glob-util.h \ src/systemd/sd-adapt/glob-util.h \
src/systemd/sd-adapt/gunicode.h \ src/systemd/sd-adapt/gunicode.h \
src/systemd/sd-adapt/ioprio.h \ src/systemd/sd-adapt/ioprio.h \
src/systemd/sd-adapt/khash.h \ src/systemd/sd-adapt/khash.h \
src/systemd/sd-adapt/libudev.h \
src/systemd/sd-adapt/locale-util.h \ src/systemd/sd-adapt/locale-util.h \
src/systemd/sd-adapt/memfd-util.h \ src/systemd/sd-adapt/memfd-util.h \
src/systemd/sd-adapt/missing.h \ src/systemd/sd-adapt/missing.h \
@@ -1389,16 +1387,17 @@ src_libsystemd_nm_la_SOURCES = \
src/systemd/sd-adapt/procfs-util.h \ src/systemd/sd-adapt/procfs-util.h \
src/systemd/sd-adapt/raw-clone.h \ src/systemd/sd-adapt/raw-clone.h \
src/systemd/sd-adapt/sd-daemon.h \ src/systemd/sd-adapt/sd-daemon.h \
src/systemd/sd-adapt/sd-device.h \
src/systemd/sd-adapt/stat-util.h \ src/systemd/sd-adapt/stat-util.h \
src/systemd/sd-adapt/terminal-util.h \ src/systemd/sd-adapt/terminal-util.h \
src/systemd/sd-adapt/udev-util.h \
src/systemd/sd-adapt/udev.h \
src/systemd/sd-adapt/unaligned.h \ src/systemd/sd-adapt/unaligned.h \
src/systemd/sd-adapt/user-util.h \ src/systemd/sd-adapt/user-util.h \
src/systemd/sd-adapt/virt.h \ src/systemd/sd-adapt/virt.h \
src/systemd/src/basic/alloc-util.c \ src/systemd/src/basic/alloc-util.c \
src/systemd/src/basic/alloc-util.h \ src/systemd/src/basic/alloc-util.h \
src/systemd/src/basic/async.h \ src/systemd/src/basic/async.h \
src/systemd/src/basic/env-util.c \
src/systemd/src/basic/env-util.h \
src/systemd/src/basic/escape.c \ src/systemd/src/basic/escape.c \
src/systemd/src/basic/escape.h \ src/systemd/src/basic/escape.h \
src/systemd/src/basic/ether-addr-util.c \ src/systemd/src/basic/ether-addr-util.c \

View File

@@ -1,10 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once #pragma once
/***
Copyright © 2014 Tom Gundersen
***/
#include <endian.h> #include <endian.h>
#include <stdint.h> #include <stdint.h>

View File

@@ -2,6 +2,7 @@ sources = files(
'sd-adapt/nm-sd-adapt.c', 'sd-adapt/nm-sd-adapt.c',
'src/basic/alloc-util.c', 'src/basic/alloc-util.c',
'src/basic/escape.c', 'src/basic/escape.c',
'src/basic/env-util.c',
'src/basic/ether-addr-util.c', 'src/basic/ether-addr-util.c',
'src/basic/extract-word.c', 'src/basic/extract-word.c',
'src/basic/fd-util.c', 'src/basic/fd-util.c',

View File

@@ -1,5 +0,0 @@
#pragma once
/* dummy header */
struct udev_device;

View File

@@ -1,3 +0,0 @@
#pragma once
/* dummy header */

View File

@@ -1,6 +0,0 @@
#pragma once
/* dummy header */
#include "libudev.h"
#include "strv.h"

View File

@@ -0,0 +1,791 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include "nm-sd-adapt.h"
#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"
#if 0 /* NM_IGNORED */
#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;
}
#endif /* NM_IGNORED */
int getenv_bool(const char *p) {
const char *e;
e = getenv(p);
if (!e)
return -ENXIO;
return parse_boolean(e);
}
#if 0 /* NM_IGNORED */
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);
}
#endif /* NM_IGNORED */

View File

@@ -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);

View File

@@ -1,7 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
/***
Copyright © 2014 Tom Gundersen
***/
#include "nm-sd-adapt.h" #include "nm-sd-adapt.h"

View File

@@ -1,10 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once #pragma once
/***
Copyright © 2014 Tom Gundersen
***/
#include <net/ethernet.h> #include <net/ethernet.h>
#include <stdbool.h> #include <stdbool.h>

View File

@@ -78,8 +78,12 @@ int acquire_data_fd(const void *data, size_t size, unsigned flags);
int fd_duplicate_data_fd(int fd); int fd_duplicate_data_fd(int fd);
/* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */ /* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */
/* 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) \ #define ERRNO_IS_DISCONNECT(r) \
IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH) IN_SET(r, \
ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, \
ENETUNREACH, EHOSTUNREACH, ENOPROTOOPT, EHOSTDOWN, ENONET)
/* Resource exhaustion, could be our fault or general system trouble */ /* Resource exhaustion, could be our fault or general system trouble */
#define ERRNO_IS_RESOURCE(r) \ #define ERRNO_IS_RESOURCE(r) \

View File

@@ -1235,9 +1235,13 @@ int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
const char *fn; const char *fn;
char *t; char *t;
assert(p);
assert(ret); assert(ret);
if (isempty(p))
return -EINVAL;
if (path_equal(p, "/"))
return -EINVAL;
/* /*
* Turns this: * Turns this:
* /foo/bar/waldo * /foo/bar/waldo
@@ -1269,9 +1273,13 @@ int tempfn_random(const char *p, const char *extra, char **ret) {
uint64_t u; uint64_t u;
unsigned i; unsigned i;
assert(p);
assert(ret); assert(ret);
if (isempty(p))
return -EINVAL;
if (path_equal(p, "/"))
return -EINVAL;
/* /*
* Turns this: * Turns this:
* /foo/bar/waldo * /foo/bar/waldo
@@ -1330,6 +1338,9 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) {
if (!t) if (!t)
return -ENOMEM; return -ENOMEM;
if (isempty(p))
x = stpcpy(stpcpy(t, ".#"), extra);
else
x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra); x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra);
u = random_u64(); u = random_u64();
@@ -1417,7 +1428,8 @@ int open_tmpfile_unlinkable(const char *directory, int flags) {
r = tmp_dir(&directory); r = tmp_dir(&directory);
if (r < 0) if (r < 0)
return r; return r;
} } else if (isempty(directory))
return -EINVAL;
/* Returns an unlinked temporary file that cannot be linked into the file system anymore */ /* Returns an unlinked temporary file that cannot be linked into the file system anymore */
@@ -1452,21 +1464,13 @@ 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 * 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. */ * "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */
{ fd = open_parent(target, O_TMPFILE|flags, 0640);
_cleanup_free_ char *dn = NULL;
dn = dirname_malloc(target);
if (!dn)
return -ENOMEM;
fd = open(dn, O_TMPFILE|flags, 0640);
if (fd >= 0) { if (fd >= 0) {
*ret_path = NULL; *ret_path = NULL;
return fd; return fd;
} }
log_debug_errno(errno, "Failed to use O_TMPFILE on %s: %m", dn); log_debug_errno(fd, "Failed to use O_TMPFILE for %s: %m", target);
}
r = tempfn_random(target, NULL, &tmp); r = tempfn_random(target, NULL, &tmp);
if (r < 0) if (r < 0)

View File

@@ -442,6 +442,31 @@ int mkfifo_atomic(const char *path, mode_t mode) {
return 0; 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) { int get_files_in_directory(const char *path, char ***list) {
_cleanup_closedir_ DIR *d = NULL; _cleanup_closedir_ DIR *d = NULL;
struct dirent *de; struct dirent *de;
@@ -679,7 +704,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) { 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 /* 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. */ * 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) if (r < 0)
return -errno; return -errno;
@@ -834,7 +859,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
fd_is_fs_type(child, AUTOFS_SUPER_MAGIC) > 0) fd_is_fs_type(child, AUTOFS_SUPER_MAGIC) > 0)
return -EREMOTE; return -EREMOTE;
if (S_ISLNK(st.st_mode)) { if (S_ISLNK(st.st_mode) && !((flags & CHASE_NOFOLLOW) && isempty(todo))) {
char *joined; char *joined;
_cleanup_free_ char *destination = NULL; _cleanup_free_ char *destination = NULL;
@@ -1165,7 +1190,7 @@ int unlinkat_deallocate(int fd, const char *name, int flags) {
} }
int fsync_directory_of_file(int fd) { int fsync_directory_of_file(int fd) {
_cleanup_free_ char *path = NULL, *dn = NULL; _cleanup_free_ char *path = NULL;
_cleanup_close_ int dfd = -1; _cleanup_close_ int dfd = -1;
int r; int r;
@@ -1191,17 +1216,41 @@ int fsync_directory_of_file(int fd) {
if (!path_is_absolute(path)) if (!path_is_absolute(path))
return -EINVAL; return -EINVAL;
dn = dirname_malloc(path); dfd = open_parent(path, O_CLOEXEC, 0);
if (!dn)
return -ENOMEM;
dfd = open(dn, O_RDONLY|O_CLOEXEC|O_DIRECTORY);
if (dfd < 0) if (dfd < 0)
return -errno; return dfd;
if (fsync(dfd) < 0) if (fsync(dfd) < 0)
return -errno; return -errno;
return 0; 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;
}
#endif /* NM_IGNORED */ #endif /* NM_IGNORED */

View File

@@ -42,6 +42,7 @@ int symlink_idempotent(const char *from, const char *to);
int symlink_atomic(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 mknod_atomic(const char *path, mode_t mode, dev_t dev);
int mkfifo_atomic(const char *path, mode_t mode); 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); 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_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_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_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 */ /* 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 unlinkat_deallocate(int fd, const char *name, int flags);
int fsync_directory_of_file(int fd); int fsync_directory_of_file(int fd);
int open_parent(const char *path, int flags, mode_t mode);

View File

@@ -1,7 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
/***
Copyright © 2014 Michal Schmidt
***/
#include "nm-sd-adapt.h" #include "nm-sd-adapt.h"
@@ -78,7 +75,7 @@ void trivial_hash_func(const void *p, struct siphash *state) {
} }
int trivial_compare_func(const void *a, const void *b) { 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 = { const struct hash_ops trivial_hash_ops = {
@@ -94,7 +91,7 @@ int uint64_compare_func(const void *_a, const void *_b) {
uint64_t a, b; uint64_t a, b;
a = *(const uint64_t*) _a; a = *(const uint64_t*) _a;
b = *(const uint64_t*) _b; b = *(const uint64_t*) _b;
return a < b ? -1 : (a > b ? 1 : 0); return CMP(a, b);
} }
const struct hash_ops uint64_hash_ops = { const struct hash_ops uint64_hash_ops = {
@@ -112,7 +109,7 @@ int devt_compare_func(const void *_a, const void *_b) {
dev_t a, b; dev_t a, b;
a = *(const dev_t*) _a; a = *(const dev_t*) _a;
b = *(const dev_t*) _b; b = *(const dev_t*) _b;
return a < b ? -1 : (a > b ? 1 : 0); return CMP(a, b);
} }
const struct hash_ops devt_hash_ops = { const struct hash_ops devt_hash_ops = {

View File

@@ -1,10 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once #pragma once
/***
Copyright © 2014 Michal Schmidt
***/
#include "macro.h" #include "macro.h"
#include "siphash24.h" #include "siphash24.h"

View File

@@ -1,7 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
/***
Copyright © 2014 Michal Schmidt
***/
#include "nm-sd-adapt.h" #include "nm-sd-adapt.h"
@@ -11,8 +8,9 @@
#include <string.h> #include <string.h>
#include "alloc-util.h" #include "alloc-util.h"
#include "hashmap.h" #include "env-util.h"
#include "fileio.h" #include "fileio.h"
#include "hashmap.h"
#include "macro.h" #include "macro.h"
#include "mempool.h" #include "mempool.h"
#include "process-util.h" #include "process-util.h"
@@ -771,20 +769,31 @@ static void reset_direct_storage(HashmapBase *h) {
memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets); 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) { static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) {
HashmapBase *h; HashmapBase *h;
const struct hashmap_type_info *hi = &hashmap_type_info[type]; const struct hashmap_type_info *hi = &hashmap_type_info[type];
bool use_pool; bool up;
use_pool = is_main_thread(); up = use_pool();
h = use_pool ? mempool_alloc0_tile(hi->mempool) : malloc0(hi->head_size);
h = up ? mempool_alloc0_tile(hi->mempool) : malloc0(hi->head_size);
if (!h) if (!h)
return NULL; return NULL;
h->type = type; h->type = type;
h->from_pool = use_pool; h->from_pool = up;
h->hash_ops = hash_ops ? hash_ops : &trivial_hash_ops; h->hash_ops = hash_ops ? hash_ops : &trivial_hash_ops;
if (type == HASHMAP_TYPE_ORDERED) { if (type == HASHMAP_TYPE_ORDERED) {
@@ -862,9 +871,11 @@ static void hashmap_free_no_clear(HashmapBase *h) {
assert_se(pthread_mutex_unlock(&hashmap_debug_list_mutex) == 0); assert_se(pthread_mutex_unlock(&hashmap_debug_list_mutex) == 0);
#endif #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); mempool_free_tile(hashmap_type_info[h->type].mempool, h);
else } else
free(h); free(h);
} }

View File

@@ -1,10 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once #pragma once
/***
Copyright © 2014 Michal Schmidt
***/
#include <limits.h> #include <limits.h>
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>

View File

@@ -576,4 +576,27 @@ int in_addr_prefix_from_string_auto(
return 0; 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,
};
#endif /* NM_IGNORED */ #endif /* NM_IGNORED */

View File

@@ -5,6 +5,7 @@
#include <stddef.h> #include <stddef.h>
#include <sys/socket.h> #include <sys/socket.h>
#include "hash-funcs.h"
#include "macro.h" #include "macro.h"
#include "util.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) {}) #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;

View File

@@ -156,7 +156,7 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
#endif #endif
#define ELEMENTSOF(x) \ #define ELEMENTSOF(x) \
__extension__ (__builtin_choose_expr( \ (__builtin_choose_expr( \
!__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \ !__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \
sizeof(x)/sizeof((x)[0]), \ sizeof(x)/sizeof((x)[0]), \
VOID_0)) VOID_0))
@@ -176,7 +176,7 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
*/ */
#define container_of(ptr, type, member) __container_of(UNIQ, (ptr), type, member) #define container_of(ptr, type, member) __container_of(UNIQ, (ptr), type, member)
#define __container_of(uniq, ptr, type, member) \ #define __container_of(uniq, ptr, type, member) \
__extension__ ({ \ ({ \
const typeof( ((type*)0)->member ) *UNIQ_T(A, uniq) = (ptr); \ 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) ); \
}) })
@@ -184,7 +184,7 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
#undef MAX #undef MAX
#define MAX(a, b) __MAX(UNIQ, (a), UNIQ, (b)) #define MAX(a, b) __MAX(UNIQ, (a), UNIQ, (b))
#define __MAX(aq, a, bq, b) \ #define __MAX(aq, a, bq, b) \
__extension__ ({ \ ({ \
const typeof(a) UNIQ_T(A, aq) = (a); \ const typeof(a) UNIQ_T(A, aq) = (a); \
const typeof(b) UNIQ_T(B, bq) = (b); \ 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); \
@@ -192,7 +192,7 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
/* evaluates to (void) if _A or _B are not constant or of different types */ /* evaluates to (void) if _A or _B are not constant or of different types */
#define CONST_MAX(_A, _B) \ #define CONST_MAX(_A, _B) \
__extension__ (__builtin_choose_expr( \ (__builtin_choose_expr( \
__builtin_constant_p(_A) && \ __builtin_constant_p(_A) && \
__builtin_constant_p(_B) && \ __builtin_constant_p(_B) && \
__builtin_types_compatible_p(typeof(_A), typeof(_B)), \ __builtin_types_compatible_p(typeof(_A), typeof(_B)), \
@@ -203,7 +203,7 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
#define MAXSIZE(A, B) (sizeof(union _packed_ { typeof(A) a; typeof(B) b; })) #define MAXSIZE(A, B) (sizeof(union _packed_ { typeof(A) a; typeof(B) b; }))
#define MAX3(x, y, z) \ #define MAX3(x, y, z) \
__extension__ ({ \ ({ \
const typeof(x) _c = MAX(x, y); \ const typeof(x) _c = MAX(x, y); \
MAX(_c, z); \ MAX(_c, z); \
}) })
@@ -211,30 +211,39 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
#undef MIN #undef MIN
#define MIN(a, b) __MIN(UNIQ, (a), UNIQ, (b)) #define MIN(a, b) __MIN(UNIQ, (a), UNIQ, (b))
#define __MIN(aq, a, bq, b) \ #define __MIN(aq, a, bq, b) \
__extension__ ({ \ ({ \
const typeof(a) UNIQ_T(A, aq) = (a); \ const typeof(a) UNIQ_T(A, aq) = (a); \
const typeof(b) UNIQ_T(B, bq) = (b); \ 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) \ #define MIN3(x, y, z) \
__extension__ ({ \ ({ \
const typeof(x) _c = MIN(x, y); \ const typeof(x) _c = MIN(x, y); \
MIN(_c, z); \ MIN(_c, z); \
}) })
#define LESS_BY(a, b) __LESS_BY(UNIQ, (a), UNIQ, (b)) #define LESS_BY(a, b) __LESS_BY(UNIQ, (a), UNIQ, (b))
#define __LESS_BY(aq, a, bq, b) \ #define __LESS_BY(aq, a, bq, b) \
__extension__ ({ \ ({ \
const typeof(a) UNIQ_T(A, aq) = (a); \ const typeof(a) UNIQ_T(A, aq) = (a); \
const typeof(b) UNIQ_T(B, bq) = (b); \ 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) ? 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) ? -1 : \
UNIQ_T(A, aq) > UNIQ_T(B, bq) ? 1 : 0; \
})
#undef CLAMP #undef CLAMP
#define CLAMP(x, low, high) __CLAMP(UNIQ, (x), UNIQ, (low), UNIQ, (high)) #define CLAMP(x, low, high) __CLAMP(UNIQ, (x), UNIQ, (low), UNIQ, (high))
#define __CLAMP(xq, x, lowq, low, highq, high) \ #define __CLAMP(xq, x, lowq, low, highq, high) \
__extension__ ({ \ ({ \
const typeof(x) UNIQ_T(X, xq) = (x); \ const typeof(x) UNIQ_T(X, xq) = (x); \
const typeof(low) UNIQ_T(LOW, lowq) = (low); \ const typeof(low) UNIQ_T(LOW, lowq) = (low); \
const typeof(high) UNIQ_T(HIGH, highq) = (high); \ const typeof(high) UNIQ_T(HIGH, highq) = (high); \
@@ -250,18 +259,54 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
* [x / y + !!(x % y)]. Note that on "Real CPUs" a division returns both the * [x / y + !!(x % y)]. Note that on "Real CPUs" a division returns both the
* quotient and the remainder, so both should be equally fast. */ * quotient and the remainder, so both should be equally fast. */
#define DIV_ROUND_UP(_x, _y) \ #define DIV_ROUND_UP(_x, _y) \
__extension__ ({ \ ({ \
const typeof(_x) __x = (_x); \ const typeof(_x) __x = (_x); \
const typeof(_y) __y = (_y); \ const typeof(_y) __y = (_y); \
(__x / __y + !!(__x % __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) \ #define assert_message_se(expr, message) \
do { \ do { \
if (_unlikely_(!(expr))) \ if (_unlikely_(!(expr))) \
log_assert_failed(message, __FILE__, __LINE__, __PRETTY_FUNCTION__); \ log_assert_failed(message, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
} while (false) } 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) #define assert_se(expr) assert_message_se(expr, #expr)
/* We override the glibc assert() here. */ /* We override the glibc assert() here. */
@@ -294,10 +339,6 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
REENABLE_WARNING REENABLE_WARNING
#endif #endif
#define assert_log(expr, message) ((_likely_(expr)) \
? (true) \
: (log_assert_failed_return(message, __FILE__, __LINE__, __PRETTY_FUNCTION__), false))
#define assert_return(expr, r) \ #define assert_return(expr, r) \
do { \ do { \
if (!assert_log(expr, #expr)) \ if (!assert_log(expr, #expr)) \

View File

@@ -1,7 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
/***
Copyright © 2014 Michal Schmidt
***/
#include "nm-sd-adapt.h" #include "nm-sd-adapt.h"

View File

@@ -1,10 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once #pragma once
/***
Copyright © 2014 Michal Schmidt
***/
#include <stddef.h> #include <stddef.h>
struct pool; struct pool;

View File

@@ -642,6 +642,8 @@ int parse_permille_unbounded(const char *p) {
r = safe_atoi(n, &v); r = safe_atoi(n, &v);
if (r < 0) if (r < 0)
return r; return r;
if (v < 0)
return -ERANGE;
} else { } else {
pc = endswith(p, "%"); pc = endswith(p, "%");
if (!pc) if (!pc)
@@ -662,15 +664,14 @@ int parse_permille_unbounded(const char *p) {
r = safe_atoi(n, &v); r = safe_atoi(n, &v);
if (r < 0) if (r < 0)
return r; return r;
if (v < 0)
return -ERANGE;
if (v > (INT_MAX - q) / 10) if (v > (INT_MAX - q) / 10)
return -ERANGE; return -ERANGE;
v = v * 10 + q; v = v * 10 + q;
} }
if (v < 0)
return -ERANGE;
return v; return v;
} }

View File

@@ -113,10 +113,7 @@ int path_make_absolute_cwd(const char *p, char **ret) {
if (r < 0) if (r < 0)
return r; return r;
if (endswith(cwd, "/")) c = path_join(NULL, cwd, p);
c = strjoin(cwd, p);
else
c = strjoin(cwd, "/", p);
} }
if (!c) if (!c)
return -ENOMEM; return -ENOMEM;
@@ -426,6 +423,7 @@ char* path_startswith(const char *path, const char *prefix) {
prefix += b; prefix += b;
} }
} }
#endif /* NM_IGNORED */
int path_compare(const char *a, const char *b) { int path_compare(const char *a, const char *b) {
int d; int d;
@@ -477,6 +475,7 @@ bool path_equal(const char *a, const char *b) {
return path_compare(a, b) == 0; return path_compare(a, b) == 0;
} }
#if 0 /* NM_IGNORED */
bool path_equal_or_files_same(const char *a, const char *b, int flags) { bool path_equal_or_files_same(const char *a, const char *b, int flags) {
return path_equal(a, b) || files_same(a, b, flags) > 0; return path_equal(a, b) || files_same(a, b, flags) > 0;
} }

View File

@@ -60,10 +60,10 @@ static inline bool path_equal_ptr(const char *a, const char *b) {
/* Note: the search terminates on the first NULL item. */ /* Note: the search terminates on the first NULL item. */
#define PATH_IN_SET(p, ...) \ #define PATH_IN_SET(p, ...) \
({ \ ({ \
char **s; \ char **_s; \
bool _found = false; \ bool _found = false; \
STRV_FOREACH(s, STRV_MAKE(__VA_ARGS__)) \ STRV_FOREACH(_s, STRV_MAKE(__VA_ARGS__)) \
if (path_equal(p, *s)) { \ if (path_equal(p, *_s)) { \
_found = true; \ _found = true; \
break; \ break; \
} \ } \

View File

@@ -1115,12 +1115,7 @@ int pid_compare_func(const void *a, const void *b) {
const pid_t *p = a, *q = b; const pid_t *p = a, *q = b;
/* Suitable for usage in qsort() */ /* Suitable for usage in qsort() */
return CMP(*p, *q);
if (*p < *q)
return -1;
if (*p > *q)
return 1;
return 0;
} }
int ioprio_parse_priority(const char *s, int *ret) { int ioprio_parse_priority(const char *s, int *ret) {
@@ -1161,7 +1156,7 @@ void reset_cached_pid(void) {
/* We use glibc __register_atfork() + __dso_handle directly here, as they are not included in the glibc /* 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 * 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. */ * 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__)); extern void* __dso_handle __attribute__ ((__weak__));
pid_t getpid_cached(void) { pid_t getpid_cached(void) {

View File

@@ -2,6 +2,10 @@
#include "nm-sd-adapt.h" #include "nm-sd-adapt.h"
#ifdef __x86_64__
#include <cpuid.h>
#endif
#include <elf.h> #include <elf.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
@@ -28,6 +32,41 @@
#include "random-util.h" #include "random-util.h"
#include "time-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) { int acquire_random_bytes(void *p, size_t n, bool high_quality_required) {
static int have_syscall = -1; static int have_syscall = -1;
@@ -77,8 +116,26 @@ int acquire_random_bytes(void *p, size_t n, bool high_quality_required) {
* a best-effort basis. */ * a best-effort basis. */
have_syscall = true; have_syscall = true;
if (!high_quality_required) 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; 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 } else
return -errno; return -errno;
} }

View File

@@ -21,3 +21,5 @@ static inline uint32_t random_u32(void) {
random_bytes(&u, sizeof(u)); random_bytes(&u, sizeof(u));
return u; return u;
} }
int rdrand64(uint64_t *ret);

View File

@@ -53,7 +53,8 @@ static const char* const socket_address_type_table[] = {
DEFINE_STRING_TABLE_LOOKUP(socket_address_type, int); DEFINE_STRING_TABLE_LOOKUP(socket_address_type, int);
int socket_address_parse(SocketAddress *a, const char *s) { int socket_address_parse(SocketAddress *a, const char *s) {
char *e, *n; _cleanup_free_ char *n = NULL;
char *e;
int r; int r;
assert(a); assert(a);
@@ -71,7 +72,9 @@ int socket_address_parse(SocketAddress *a, const char *s) {
if (!e) if (!e)
return -EINVAL; return -EINVAL;
n = strndupa(s+1, e-s-1); n = strndup(s+1, e-s-1);
if (!n)
return -ENOMEM;
errno = 0; errno = 0;
if (inet_pton(AF_INET6, n, &a->sockaddr.in6.sin6_addr) <= 0) if (inet_pton(AF_INET6, n, &a->sockaddr.in6.sin6_addr) <= 0)
@@ -128,7 +131,10 @@ int socket_address_parse(SocketAddress *a, const char *s) {
if (r < 0) if (r < 0)
return r; return r;
n = strndupa(cid_start, e - cid_start); n = strndup(cid_start, e - cid_start);
if (!n)
return -ENOMEM;
if (!isempty(n)) { if (!isempty(n)) {
r = safe_atou(n, &a->sockaddr.vm.svm_cid); r = safe_atou(n, &a->sockaddr.vm.svm_cid);
if (r < 0) if (r < 0)
@@ -149,7 +155,9 @@ int socket_address_parse(SocketAddress *a, const char *s) {
if (r < 0) if (r < 0)
return r; return r;
n = strndupa(s, e-s); n = strndup(s, e-s);
if (!n)
return -ENOMEM;
/* IPv4 in w.x.y.z:p notation? */ /* IPv4 in w.x.y.z:p notation? */
r = inet_pton(AF_INET, n, &a->sockaddr.in.sin_addr); r = inet_pton(AF_INET, n, &a->sockaddr.in.sin_addr);
@@ -1006,9 +1014,10 @@ int getpeergroups(int fd, gid_t **ret) {
return (int) n; return (int) n;
} }
int send_one_fd_sa( ssize_t send_one_fd_iov_sa(
int transport_fd, int transport_fd,
int fd, int fd,
struct iovec *iov, size_t iovlen,
const struct sockaddr *sa, socklen_t len, const struct sockaddr *sa, socklen_t len,
int flags) { int flags) {
@@ -1019,13 +1028,25 @@ int send_one_fd_sa(
struct msghdr mh = { struct msghdr mh = {
.msg_name = (struct sockaddr*) sa, .msg_name = (struct sockaddr*) sa,
.msg_namelen = len, .msg_namelen = len,
.msg_control = &control, .msg_iov = iov,
.msg_controllen = sizeof(control), .msg_iovlen = iovlen,
}; };
struct cmsghdr *cmsg; ssize_t k;
assert(transport_fd >= 0); assert(transport_fd >= 0);
assert(fd >= 0);
/*
* We need either an FD or data to send.
* If there's nothing, return an error.
*/
if (fd < 0 && !iov)
return -EINVAL;
if (fd >= 0) {
struct cmsghdr *cmsg;
mh.msg_control = &control;
mh.msg_controllen = sizeof(control);
cmsg = CMSG_FIRSTHDR(&mh); cmsg = CMSG_FIRSTHDR(&mh);
cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_level = SOL_SOCKET;
@@ -1034,13 +1055,31 @@ int send_one_fd_sa(
memcpy(CMSG_DATA(cmsg), &fd, sizeof(int)); memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
mh.msg_controllen = CMSG_SPACE(sizeof(int)); mh.msg_controllen = CMSG_SPACE(sizeof(int));
if (sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags) < 0) }
return -errno; k = sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags);
if (k < 0)
return (ssize_t) -errno;
return 0; 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 { union {
struct cmsghdr cmsghdr; struct cmsghdr cmsghdr;
uint8_t buf[CMSG_SPACE(sizeof(int))]; uint8_t buf[CMSG_SPACE(sizeof(int))];
@@ -1048,10 +1087,14 @@ int receive_one_fd(int transport_fd, int flags) {
struct msghdr mh = { struct msghdr mh = {
.msg_control = &control, .msg_control = &control,
.msg_controllen = sizeof(control), .msg_controllen = sizeof(control),
.msg_iov = iov,
.msg_iovlen = iovlen,
}; };
struct cmsghdr *cmsg, *found = NULL; struct cmsghdr *cmsg, *found = NULL;
ssize_t k;
assert(transport_fd >= 0); assert(transport_fd >= 0);
assert(ret_fd);
/* /*
* Receive a single FD via @transport_fd. We don't care for * Receive a single FD via @transport_fd. We don't care for
@@ -1061,8 +1104,9 @@ int receive_one_fd(int transport_fd, int flags) {
* combination with send_one_fd(). * combination with send_one_fd().
*/ */
if (recvmsg(transport_fd, &mh, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC | flags) < 0) k = recvmsg(transport_fd, &mh, MSG_CMSG_CLOEXEC | flags);
return -errno; if (k < 0)
return (ssize_t) -errno;
CMSG_FOREACH(cmsg, &mh) { CMSG_FOREACH(cmsg, &mh) {
if (cmsg->cmsg_level == SOL_SOCKET && if (cmsg->cmsg_level == SOL_SOCKET &&
@@ -1074,12 +1118,33 @@ int receive_one_fd(int transport_fd, int flags) {
} }
} }
if (!found) { if (!found)
cmsg_close_all(&mh); cmsg_close_all(&mh);
/* If didn't receive an FD or any data, return an error. */
if (k == 0 && !found)
return -EIO; return -EIO;
if (found)
*ret_fd = *(int*) CMSG_DATA(found);
else
*ret_fd = -1;
return k;
} }
return *(int*) CMSG_DATA(found); 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;
} }
#endif /* NM_IGNORED */ #endif /* NM_IGNORED */

View File

@@ -132,11 +132,19 @@ int getpeercred(int fd, struct ucred *ucred);
int getpeersec(int fd, char **ret); int getpeersec(int fd, char **ret);
int getpeergroups(int fd, gid_t **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 send_one_fd_sa(int transport_fd,
int fd, int fd,
const struct sockaddr *sa, socklen_t len, const struct sockaddr *sa, socklen_t len,
int flags); 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); int receive_one_fd(int transport_fd, int flags);
ssize_t next_datagram_size_fd(int fd); ssize_t next_datagram_size_fd(int fd);

View File

@@ -48,6 +48,17 @@ int is_dir(const char* path, bool follow) {
return !!S_ISDIR(st.st_mode); 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) { int is_device_node(const char *path) {
struct stat info; struct stat info;

View File

@@ -12,6 +12,7 @@
int is_symlink(const char *path); int is_symlink(const char *path);
int is_dir(const char *path, bool follow); int is_dir(const char *path, bool follow);
int is_dir_fd(int fd);
int is_device_node(const char *path); int is_device_node(const char *path);
int dir_is_empty(const char *path); int dir_is_empty(const char *path);

View File

@@ -255,6 +255,10 @@ char **strv_split(const char *s, const char *separator) {
assert(s); assert(s);
s += strspn(s, separator);
if (isempty(s))
return new0(char*, 1);
n = 0; n = 0;
FOREACH_WORD_SEPARATOR(word, l, s, separator, state) FOREACH_WORD_SEPARATOR(word, l, s, separator, state)
n++; n++;

View File

@@ -2,6 +2,7 @@
#include "nm-sd-adapt.h" #include "nm-sd-adapt.h"
#include <ctype.h>
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#include <stdlib.h> #include <stdlib.h>
@@ -1001,10 +1002,10 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
} }
for (;;) { for (;;) {
long long l, z = 0;
char *e;
unsigned n = 0;
usec_t multiplier = default_unit, k; usec_t multiplier = default_unit, k;
long long l, z = 0;
unsigned n = 0;
char *e;
p += strspn(p, WHITESPACE); p += strspn(p, WHITESPACE);
@@ -1015,6 +1016,9 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
break; break;
} }
if (*p == '-') /* Don't allow "-0" */
return -ERANGE;
errno = 0; errno = 0;
l = strtoll(p, &e, 10); l = strtoll(p, &e, 10);
if (errno > 0) if (errno > 0)
@@ -1025,14 +1029,16 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
if (*e == '.') { if (*e == '.') {
char *b = e + 1; char *b = e + 1;
/* Don't allow "0.-0", "3.+1" or "3. 1" */
if (*b == '-' || *b == '+' || isspace(*b))
return -EINVAL;
errno = 0; errno = 0;
z = strtoll(b, &e, 10); z = strtoll(b, &e, 10);
if (errno > 0) if (errno > 0)
return -errno; return -errno;
if (z < 0) if (z < 0)
return -ERANGE; return -ERANGE;
if (e == b) if (e == b)
return -EINVAL; return -EINVAL;
@@ -1149,26 +1155,28 @@ int parse_nsec(const char *t, nsec_t *nsec) {
break; break;
} }
if (*p == '-')
return -ERANGE;
errno = 0; errno = 0;
l = strtoll(p, &e, 10); l = strtoll(p, &e, 10);
if (errno > 0) if (errno > 0)
return -errno; return -errno;
if (l < 0) if (l < 0)
return -ERANGE; return -ERANGE;
if (*e == '.') { if (*e == '.') {
char *b = e + 1; char *b = e + 1;
if (*b == '-' || *b == '+' || isspace(*b))
return -EINVAL;
errno = 0; errno = 0;
z = strtoll(b, &e, 10); z = strtoll(b, &e, 10);
if (errno > 0) if (errno > 0)
return -errno; return -errno;
if (z < 0) if (z < 0)
return -ERANGE; return -ERANGE;
if (e == b) if (e == b)
return -EINVAL; return -EINVAL;

View File

@@ -1,7 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
/***
Copyright © 2008-2011 Kay Sievers
***/
/* Parts of this file are based on the GLIB utf8 validation functions. The /* Parts of this file are based on the GLIB utf8 validation functions. The
* original license text follows. */ * original license text follows. */

View File

@@ -82,31 +82,6 @@ bool display_is_local(const char *display) {
display[1] <= '9'; 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) { bool kexec_loaded(void) {
_cleanup_free_ char *s = NULL; _cleanup_free_ char *s = NULL;
@@ -260,6 +235,11 @@ int container_get_leader(const char *machine, pid_t *pid) {
assert(machine); assert(machine);
assert(pid); assert(pid);
if (streq(machine, ".host")) {
*pid = 1;
return 0;
}
if (!machine_name_is_valid(machine)) if (!machine_name_is_valid(machine))
return -EINVAL; return -EINVAL;

View File

@@ -50,7 +50,6 @@ static inline const char* enable_disable(bool b) {
bool plymouth_running(void); bool plymouth_running(void);
bool display_is_local(const char *display) _pure_; bool display_is_local(const char *display) _pure_;
int socket_from_display(const char *display, char **path);
#define NULSTR_FOREACH(i, l) \ #define NULSTR_FOREACH(i, l) \
for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1) 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); 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) { static inline void memcpy_safe(void *dst, const void *src, size_t n) {
if (n == 0) if (n == 0)
return; return;
@@ -123,6 +120,15 @@ static inline void memcpy_safe(void *dst, const void *src, size_t n) {
memcpy(dst, src, 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); int on_ac_power(void);
#define memzero(x,l) (memset((x), 0, (l))) #define memzero(x,l) (memset((x), 0, (l)))

View File

@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
/*** /***
Copyright © 2014 Axis Communications AB. All rights reserved. Copyright © 2014 Axis Communications AB. All rights reserved.
Copyright © 2015 Tom Gundersen
***/ ***/
#include "nm-sd-adapt.h" #include "nm-sd-adapt.h"

View File

@@ -1,11 +1,11 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
/***
Copyright © 2015 Tom Gundersen <teg@jklmen>
***/
#include "nm-sd-adapt.h" #include "nm-sd-adapt.h"
#include "libudev.h" #include <linux/if_infiniband.h>
#include <net/if_arp.h>
#include "sd-device.h"
#include "sd-id128.h" #include "sd-id128.h"
#include "dhcp-identifier.h" #include "dhcp-identifier.h"
@@ -13,7 +13,6 @@
#include "network-internal.h" #include "network-internal.h"
#include "siphash24.h" #include "siphash24.h"
#include "sparse-endian.h" #include "sparse-endian.h"
#include "udev-util.h"
#include "virt.h" #include "virt.h"
#if 0 /* NM_IGNORED */ #if 0 /* NM_IGNORED */
@@ -23,6 +22,8 @@
#define SYSTEMD_PEN 43793 #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 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) { int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
struct duid d; struct duid d;
@@ -55,6 +56,58 @@ int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
return 0; return 0;
} }
#if 0 /* NM_IGNORED */
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;
}
#endif /* NM_IGNORED */
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) { int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
sd_id128_t machine_id; sd_id128_t machine_id;
uint64_t hash; uint64_t hash;
@@ -73,18 +126,39 @@ int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
*len = sizeof(duid->type) + sizeof(duid->en); *len = sizeof(duid->type) + sizeof(duid->en);
/* a bit of snake-oil perhaps, but no need to expose the machine-id /* 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)); hash = htole64(siphash24(&machine_id, sizeof(machine_id), HASH_KEY.bytes));
memcpy(duid->en.id, &hash, sizeof(duid->en.id)); memcpy(duid->en.id, &hash, sizeof(duid->en.id));
return 0; return 0;
} }
#if 0 /* NM_IGNORED */
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;
}
#endif
int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id) { int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id) {
#if 0 /* NM_IGNORED */ #if 0 /* NM_IGNORED */
/* name is a pointer to memory in the udev_device struct, so must /* name is a pointer to memory in the sd_device struct, so must
have the same scope */ * have the same scope */
_cleanup_(udev_device_unrefp) struct udev_device *device = NULL; _cleanup_(sd_device_unrefp) sd_device *device = NULL;
#else /* NM_IGNORED */ #else /* NM_IGNORED */
char name_buf[IF_NAMESIZE]; char name_buf[IF_NAMESIZE];
#endif /* NM_IGNORED */ #endif /* NM_IGNORED */
@@ -94,17 +168,15 @@ int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_i
#if 0 /* NM_IGNORED */ #if 0 /* NM_IGNORED */
if (detect_container() <= 0) { if (detect_container() <= 0) {
/* not in a container, udev will be around */ /* not in a container, udev will be around */
_cleanup_(udev_unrefp) struct udev *udev;
char ifindex_str[2 + DECIMAL_STR_MAX(int)]; char ifindex_str[2 + DECIMAL_STR_MAX(int)];
int initialized, r;
udev = udev_new();
if (!udev)
return -ENOMEM;
sprintf(ifindex_str, "n%d", ifindex); sprintf(ifindex_str, "n%d", ifindex);
device = udev_device_new_from_device_id(udev, ifindex_str); if (sd_device_new_from_device_id(&device, ifindex_str) >= 0) {
if (device) { r = sd_device_get_is_initialized(device, &initialized);
if (udev_device_get_is_initialized(device) <= 0) if (r < 0)
return r;
if (!initialized)
/* not yet ready */ /* not yet ready */
return -EBUSY; return -EBUSY;

View File

@@ -1,14 +1,11 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once #pragma once
/***
Copyright © 2015 Tom Gundersen <teg@jklmen>
***/
#include "sd-id128.h" #include "sd-id128.h"
#include "macro.h" #include "macro.h"
#include "sparse-endian.h" #include "sparse-endian.h"
#include "time-util.h"
#include "unaligned.h" #include "unaligned.h"
typedef enum DUIDType { typedef enum DUIDType {
@@ -31,18 +28,18 @@ struct duid {
union { union {
struct { struct {
/* DUID_TYPE_LLT */ /* DUID_TYPE_LLT */
uint16_t htype; be16_t htype;
uint32_t time; be32_t time;
uint8_t haddr[0]; uint8_t haddr[0];
} _packed_ llt; } _packed_ llt;
struct { struct {
/* DUID_TYPE_EN */ /* DUID_TYPE_EN */
uint32_t pen; be32_t pen;
uint8_t id[8]; uint8_t id[8];
} _packed_ en; } _packed_ en;
struct { struct {
/* DUID_TYPE_LL */ /* DUID_TYPE_LL */
int16_t htype; be16_t htype;
uint8_t haddr[0]; uint8_t haddr[0];
} _packed_ ll; } _packed_ ll;
struct { struct {
@@ -56,5 +53,8 @@ struct duid {
} _packed_; } _packed_;
int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len); 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_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); int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id);

View File

@@ -3,7 +3,6 @@
/*** /***
Copyright © 2013 Intel Corporation. All rights reserved. Copyright © 2013 Intel Corporation. All rights reserved.
Copyright © 2014 Tom Gundersen
***/ ***/
#include <linux/if_packet.h> #include <linux/if_packet.h>

View File

@@ -3,7 +3,6 @@
/*** /***
Copyright © 2013 Intel Corporation. All rights reserved. Copyright © 2013 Intel Corporation. All rights reserved.
Copyright © 2014 Tom Gundersen
***/ ***/
#include <stdint.h> #include <stdint.h>

View File

@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
/*** /***
Copyright © 2013 Intel Corporation. All rights reserved. Copyright © 2013 Intel Corporation. All rights reserved.
Copyright © 2014 Tom Gundersen
***/ ***/
#include "nm-sd-adapt.h" #include "nm-sd-adapt.h"

View File

@@ -2,7 +2,6 @@
#pragma once #pragma once
/*** /***
Copyright © 2014 Tom Gundersen
Copyright © 2014-2015 Intel Corporation. All rights reserved. Copyright © 2014-2015 Intel Corporation. All rights reserved.
***/ ***/

View File

@@ -1,11 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once #pragma once
/***
Copyright © 2014 Tom Gundersen
Copyright © 2014 Susant Sahani
***/
#include "sd-event.h" #include "sd-event.h"
#include "sd-lldp.h" #include "sd-lldp.h"

View File

@@ -28,22 +28,15 @@ static int lldp_neighbor_id_compare_func(const void *a, const void *b) {
if (r != 0) if (r != 0)
return r; return r;
if (x->chassis_id_size < y->chassis_id_size) r = CMP(x->chassis_id_size, y->chassis_id_size);
return -1; if (r != 0)
return r;
if (x->chassis_id_size > y->chassis_id_size)
return 1;
r = memcmp(x->port_id, y->port_id, MIN(x->port_id_size, y->port_id_size)); r = memcmp(x->port_id, y->port_id, MIN(x->port_id_size, y->port_id_size));
if (r != 0) if (r != 0)
return r; return r;
if (x->port_id_size < y->port_id_size) return CMP(x->port_id_size, y->port_id_size);
return -1;
if (x->port_id_size > y->port_id_size)
return 1;
return 0;
} }
const struct hash_ops lldp_neighbor_id_hash_ops = { const struct hash_ops lldp_neighbor_id_hash_ops = {
@@ -54,13 +47,7 @@ const struct hash_ops lldp_neighbor_id_hash_ops = {
int lldp_neighbor_prioq_compare_func(const void *a, const void *b) { int lldp_neighbor_prioq_compare_func(const void *a, const void *b) {
const sd_lldp_neighbor *x = a, *y = b; const sd_lldp_neighbor *x = a, *y = b;
if (x->until < y->until) return CMP(x->until, y->until);
return -1;
if (x->until > y->until)
return 1;
return 0;
} }
_public_ sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n) { _public_ sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n) {

View File

@@ -1,8 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
/***
Copyright © 2014 Tom Gundersen
Copyright © 2014 Susant Sahani
***/
#include "nm-sd-adapt.h" #include "nm-sd-adapt.h"

View File

@@ -1,11 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once #pragma once
/***
Copyright © 2014 Tom Gundersen
Copyright © 2014 Susant Sahani
***/
#include "sd-event.h" #include "sd-event.h"
int lldp_network_bind_raw_socket(int ifindex); int lldp_network_bind_raw_socket(int ifindex);

View File

@@ -1,7 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
/***
Copyright © 2013 Tom Gundersen <teg@jklm.no>
***/
#include "nm-sd-adapt.h" #include "nm-sd-adapt.h"
@@ -29,24 +26,22 @@
#include "util.h" #include "util.h"
#if 0 /* NM_IGNORED */ #if 0 /* NM_IGNORED */
const char *net_get_name(struct udev_device *device) { const char *net_get_name(sd_device *device) {
const char *name, *field; const char *name, *field;
assert(device); assert(device);
/* fetch some persistent data unique (on this machine) to this 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") { 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 (sd_device_get_property_value(device, field, &name) >= 0)
if (name)
return name; return name;
}
return NULL; return NULL;
} }
#define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a) #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; size_t l, sz = 0;
const char *name = NULL; const char *name = NULL;
int r; int r;
@@ -130,7 +125,7 @@ bool net_match_config(Set *match_mac,
if (match_arch && condition_test(match_arch) <= 0) if (match_arch && condition_test(match_arch) <= 0)
return false; 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; return false;
if (!net_condition_test_strv(match_paths, dev_path)) if (!net_condition_test_strv(match_paths, dev_path))

View File

@@ -1,18 +1,14 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once #pragma once
/***
Copyright © 2013 Tom Gundersen <teg@jklm.no>
***/
#include <stdbool.h> #include <stdbool.h>
#include "sd-device.h"
#include "sd-dhcp-lease.h" #include "sd-dhcp-lease.h"
#include "condition.h" #include "condition.h"
#include "conf-parser.h" #include "conf-parser.h"
#include "set.h" #include "set.h"
#include "udev.h"
#define LINK_BRIDGE_PORT_PRIORITY_INVALID 128 #define LINK_BRIDGE_PORT_PRIORITY_INVALID 128
#define LINK_BRIDGE_PORT_PRIORITY_MAX 63 #define LINK_BRIDGE_PORT_PRIORITY_MAX 63
@@ -42,10 +38,10 @@ CONFIG_PARSER_PROTOTYPE(config_parse_ifnames);
CONFIG_PARSER_PROTOTYPE(config_parse_ifalias); CONFIG_PARSER_PROTOTYPE(config_parse_ifalias);
CONFIG_PARSER_PROTOTYPE(config_parse_iaid); CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
CONFIG_PARSER_PROTOTYPE(config_parse_bridge_port_priority); CONFIG_PARSER_PROTOTYPE(config_parse_bridge_port_priority);
#endif /* NM_IGNORED */
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);
const char *net_get_name(struct udev_device *device); const char *net_get_name(sd_device *device);
#endif /* NM_IGNORED */
void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size); 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); int deserialize_in_addrs(struct in_addr **addresses, const char *string);

View File

@@ -345,13 +345,14 @@ int sd_dhcp_client_set_client_id(
* without further modification. Otherwise, if duid_type is supported, DUID * without further modification. Otherwise, if duid_type is supported, DUID
* is set based on that type. Otherwise, an error is returned. * 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, sd_dhcp_client *client,
uint32_t iaid, uint32_t iaid,
bool append_iaid, bool append_iaid,
uint16_t duid_type, uint16_t duid_type,
const void *duid, const void *duid,
size_t duid_len) { size_t duid_len,
usec_t llt_time) {
DHCP_CLIENT_DONT_DESTROY(client); DHCP_CLIENT_DONT_DESTROY(client);
int r; int r;
@@ -385,18 +386,43 @@ static int dhcp_client_set_iaid_duid(
client->client_id.ns.duid.type = htobe16(duid_type); client->client_id.ns.duid.type = htobe16(duid_type);
memcpy(&client->client_id.ns.duid.raw.data, duid, duid_len); memcpy(&client->client_id.ns.duid.raw.data, duid, duid_len);
len = sizeof(client->client_id.ns.duid.type) + duid_len; len = sizeof(client->client_id.ns.duid.type) + duid_len;
} else if (duid_type == DUID_TYPE_EN) { } else
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); r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &len);
if (r < 0) if (r < 0)
return r; return r;
} else break;
case DUID_TYPE_LL:
if (!client->mac_addr || client->mac_addr_len == 0)
return -EOPNOTSUPP; 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 + client->client_id_len = sizeof(client->client_id.type) + len +
(append_iaid ? sizeof(client->client_id.ns.iaid) : 0); (append_iaid ? sizeof(client->client_id.ns.iaid) : 0);
if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) { 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); client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
sd_dhcp_client_start(client); sd_dhcp_client_start(client);
} }
@@ -410,7 +436,14 @@ int sd_dhcp_client_set_iaid_duid(
uint16_t duid_type, uint16_t duid_type,
const void *duid, const void *duid,
size_t duid_len) { 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( int sd_dhcp_client_set_duid(
@@ -418,7 +451,13 @@ int sd_dhcp_client_set_duid(
uint16_t duid_type, uint16_t duid_type,
const void *duid, const void *duid,
size_t duid_len) { 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);
} }
#endif /* NM_IGNORED */ #endif /* NM_IGNORED */

View File

@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
/*** /***
Copyright © 2013 Intel Corporation. All rights reserved. Copyright © 2013 Intel Corporation. All rights reserved.
Copyright © 2014 Tom Gundersen
***/ ***/
#include "nm-sd-adapt.h" #include "nm-sd-adapt.h"
@@ -28,6 +27,7 @@
#include "parse-util.h" #include "parse-util.h"
#include "stdio-util.h" #include "stdio-util.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h"
#include "unaligned.h" #include "unaligned.h"
int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) { int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) {

View File

@@ -184,13 +184,14 @@ static int client_ensure_duid(sd_dhcp6_client *client) {
* without further modification. Otherwise, if duid_type is supported, DUID * without further modification. Otherwise, if duid_type is supported, DUID
* is set based on that type. Otherwise, an error is returned. * 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, sd_dhcp6_client *client,
uint16_t duid_type, uint16_t duid_type,
const void *duid, const void *duid,
size_t duid_len) { size_t duid_len,
usec_t llt_time) {
int r; int r;
assert_return(client, -EINVAL); assert_return(client, -EINVAL);
assert_return(duid_len == 0 || duid != NULL, -EINVAL); assert_return(duid_len == 0 || duid != NULL, -EINVAL);
assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
@@ -199,23 +200,64 @@ int sd_dhcp6_client_set_duid(
r = dhcp_validate_duid_len(duid_type, duid_len); r = dhcp_validate_duid_len(duid_type, duid_len);
if (r < 0) if (r < 0)
return r; return r;
}
if (duid != NULL) {
client->duid.type = htobe16(duid_type); client->duid.type = htobe16(duid_type);
memcpy(&client->duid.raw.data, duid, duid_len); memcpy(&client->duid.raw.data, duid, duid_len);
client->duid_len = sizeof(client->duid.type) + duid_len; client->duid_len = sizeof(client->duid.type) + duid_len;
} else if (duid_type == DUID_TYPE_EN) { } else
#if 0 /* NM_IGNORED */
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); r = dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
if (r < 0) if (r < 0)
return r; return r;
} else break;
case DUID_TYPE_LL:
if (!client->mac_addr || client->mac_addr_len == 0)
return -EOPNOTSUPP; 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;
}
#else /* NM_IGNORED */
g_return_val_if_reached (-EINVAL);
#endif /* NM_IGNORED */
return 0; 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);
}
#if 0 /* NM_IGNORED */ #if 0 /* NM_IGNORED */
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) { int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid) {
assert_return(client, -EINVAL); assert_return(client, -EINVAL);
assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
@@ -1148,7 +1190,6 @@ static int client_receive_message(
return 0; return 0;
} }
if (r >= 0)
log_dhcp6_client(client, "Recv %s", log_dhcp6_client(client, "Recv %s",
dhcp6_message_type_to_string(message->type)); dhcp6_message_type_to_string(message->type));

View File

@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
/*** /***
Copyright © 2014 Tom Gundersen
Copyright © 2014-2015 Intel Corporation. All rights reserved. Copyright © 2014-2015 Intel Corporation. All rights reserved.
***/ ***/

View File

@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
/*** /***
Copyright © 2014 Axis Communications AB. All rights reserved. Copyright © 2014 Axis Communications AB. All rights reserved.
Copyright © 2015 Tom Gundersen
***/ ***/
#include "nm-sd-adapt.h" #include "nm-sd-adapt.h"

View File

@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
/*** /***
Copyright © 2014 Axis Communications AB. All rights reserved. Copyright © 2014 Axis Communications AB. All rights reserved.
Copyright © 2015 Tom Gundersen
***/ ***/
#include "nm-sd-adapt.h" #include "nm-sd-adapt.h"

View File

@@ -1,8 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
/***
Copyright © 2014 Tom Gundersen
Copyright © 2014 Susant Sahani
***/
#include "nm-sd-adapt.h" #include "nm-sd-adapt.h"

View File

@@ -1,6 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
/***
***/
#include "nm-sd-adapt.h" #include "nm-sd-adapt.h"
@@ -94,7 +92,7 @@ struct sd_event_source {
char *description; char *description;
EventSourceType type:5; EventSourceType type:5;
int enabled:3; signed int enabled:3;
bool pending:1; bool pending:1;
bool dispatching:1; bool dispatching:1;
bool floating:1; bool floating:1;

View File

@@ -1,6 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
/***
***/
#include "nm-sd-adapt.h" #include "nm-sd-adapt.h"

View File

@@ -1,9 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once #pragma once
/***
***/
#include <stdbool.h> #include <stdbool.h>
#include "sd-id128.h" #include "sd-id128.h"

View File

@@ -1,6 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
/***
***/
#include "nm-sd-adapt.h" #include "nm-sd-adapt.h"

View File

@@ -1,6 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
/***
***/
#include "nm-sd-adapt.h" #include "nm-sd-adapt.h"
@@ -514,7 +512,7 @@ int dns_name_compare_func(const void *a, const void *b) {
r = dns_label_unescape_suffix(a, &x, la, sizeof(la)); r = dns_label_unescape_suffix(a, &x, la, sizeof(la));
q = dns_label_unescape_suffix(b, &y, lb, sizeof(lb)); q = dns_label_unescape_suffix(b, &y, lb, sizeof(lb));
if (r < 0 || q < 0) if (r < 0 || q < 0)
return r - q; return CMP(r, q);
r = ascii_strcasecmp_nn(la, r, lb, q); r = ascii_strcasecmp_nn(la, r, lb, q);
if (r != 0) if (r != 0)

View File

@@ -1,9 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once #pragma once
/***
***/
#include <errno.h> #include <errno.h>
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>

View File

@@ -3,7 +3,6 @@
#define foosdcommonhfoo #define foosdcommonhfoo
/*** /***
systemd is free software; you can redistribute it and/or modify it 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 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 the Free Software Foundation; either version 2.1 of the License, or

View File

@@ -131,11 +131,18 @@ int sd_dhcp_client_set_iaid_duid(
uint16_t duid_type, uint16_t duid_type,
const void *duid, const void *duid,
size_t duid_len); 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( int sd_dhcp_client_set_duid(
sd_dhcp_client *client, sd_dhcp_client *client,
uint16_t duid_type, uint16_t duid_type,
const void *duid, const void *duid,
size_t duid_len); 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( int sd_dhcp_client_get_client_id(
sd_dhcp_client *client, sd_dhcp_client *client,
uint8_t *type, uint8_t *type,

View File

@@ -4,8 +4,6 @@
/*** /***
Copyright © 2013 Intel Corporation. All rights reserved. Copyright © 2013 Intel Corporation. All rights reserved.
Copyright © 2014 Tom Gundersen
systemd is free software; you can redistribute it and/or modify it 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 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 the Free Software Foundation; either version 2.1 of the License, or

View File

@@ -102,6 +102,9 @@ int sd_dhcp6_client_set_duid(
uint16_t duid_type, uint16_t duid_type,
const void *duid, const void *duid,
size_t duid_len); 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( int sd_dhcp6_client_set_iaid(
sd_dhcp6_client *client, sd_dhcp6_client *client,
uint32_t iaid); uint32_t iaid);

View File

@@ -3,7 +3,6 @@
#define foosddhcp6leasehfoo #define foosddhcp6leasehfoo
/*** /***
Copyright © 2014 Tom Gundersen
Copyright © 2014-2015 Intel Corporation. All rights reserved. Copyright © 2014-2015 Intel Corporation. All rights reserved.
systemd is free software; you can redistribute it and/or modify it systemd is free software; you can redistribute it and/or modify it

View File

@@ -3,7 +3,6 @@
#define foosdeventhfoo #define foosdeventhfoo
/*** /***
systemd is free software; you can redistribute it and/or modify it 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 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 the Free Software Foundation; either version 2.1 of the License, or

View File

@@ -3,7 +3,6 @@
#define foosdid128hfoo #define foosdid128hfoo
/*** /***
systemd is free software; you can redistribute it and/or modify it 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 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 the Free Software Foundation; either version 2.1 of the License, or

View File

@@ -4,8 +4,6 @@
/*** /***
Copyright © 2014 Axis Communications AB. All rights reserved. Copyright © 2014 Axis Communications AB. All rights reserved.
Copyright © 2015 Tom Gundersen
systemd is free software; you can redistribute it and/or modify it 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 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 the Free Software Foundation; either version 2.1 of the License, or

View File

@@ -3,9 +3,6 @@
#define foosdlldphfoo #define foosdlldphfoo
/*** /***
Copyright © 2014 Tom Gundersen
Copyright © 2014 Susant Sahani
systemd is free software; you can redistribute it and/or modify it 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 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 the Free Software Foundation; either version 2.1 of the License, or