mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-06 04:40:32 +01:00
merge: merge branch 'systemd' into master
This commit is contained in:
commit
2fa4c039bc
30 changed files with 1008 additions and 330 deletions
|
|
@ -74,6 +74,8 @@ libsystemd_nm_la_SOURCES = \
|
|||
systemd/src/basic/escape.h \
|
||||
systemd/src/basic/ether-addr-util.c \
|
||||
systemd/src/basic/ether-addr-util.h \
|
||||
systemd/src/basic/extract-word.c \
|
||||
systemd/src/basic/extract-word.h \
|
||||
systemd/src/basic/fd-util.c \
|
||||
systemd/src/basic/fd-util.h \
|
||||
systemd/src/basic/fileio.c \
|
||||
|
|
|
|||
302
src/systemd/src/basic/extract-word.c
Normal file
302
src/systemd/src/basic/extract-word.c
Normal file
|
|
@ -0,0 +1,302 @@
|
|||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2010 Lennart Poettering
|
||||
|
||||
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
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include "nm-sd-adapt.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "escape.h"
|
||||
#include "extract-word.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "string-util.h"
|
||||
#include "utf8.h"
|
||||
|
||||
int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
size_t allocated = 0, sz = 0;
|
||||
char c;
|
||||
int r;
|
||||
|
||||
char quote = 0; /* 0 or ' or " */
|
||||
bool backslash = false; /* whether we've just seen a backslash */
|
||||
|
||||
assert(p);
|
||||
assert(ret);
|
||||
|
||||
/* Bail early if called after last value or with no input */
|
||||
if (!*p)
|
||||
goto finish_force_terminate;
|
||||
c = **p;
|
||||
|
||||
if (!separators)
|
||||
separators = WHITESPACE;
|
||||
|
||||
/* Parses the first word of a string, and returns it in
|
||||
* *ret. Removes all quotes in the process. When parsing fails
|
||||
* (because of an uneven number of quotes or similar), leaves
|
||||
* the pointer *p at the first invalid character. */
|
||||
|
||||
if (flags & EXTRACT_DONT_COALESCE_SEPARATORS)
|
||||
if (!GREEDY_REALLOC(s, allocated, sz+1))
|
||||
return -ENOMEM;
|
||||
|
||||
for (;; (*p)++, c = **p) {
|
||||
if (c == 0)
|
||||
goto finish_force_terminate;
|
||||
else if (strchr(separators, c)) {
|
||||
if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
|
||||
(*p)++;
|
||||
goto finish_force_next;
|
||||
}
|
||||
} else {
|
||||
/* We found a non-blank character, so we will always
|
||||
* want to return a string (even if it is empty),
|
||||
* allocate it here. */
|
||||
if (!GREEDY_REALLOC(s, allocated, sz+1))
|
||||
return -ENOMEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (;; (*p)++, c = **p) {
|
||||
if (backslash) {
|
||||
if (!GREEDY_REALLOC(s, allocated, sz+7))
|
||||
return -ENOMEM;
|
||||
|
||||
if (c == 0) {
|
||||
if ((flags & EXTRACT_CUNESCAPE_RELAX) &&
|
||||
(!quote || flags & EXTRACT_RELAX)) {
|
||||
/* If we find an unquoted trailing backslash and we're in
|
||||
* EXTRACT_CUNESCAPE_RELAX mode, keep it verbatim in the
|
||||
* output.
|
||||
*
|
||||
* Unbalanced quotes will only be allowed in EXTRACT_RELAX
|
||||
* mode, EXTRACT_CUNESCAPE_RELAX mode does not allow them.
|
||||
*/
|
||||
s[sz++] = '\\';
|
||||
goto finish_force_terminate;
|
||||
}
|
||||
if (flags & EXTRACT_RELAX)
|
||||
goto finish_force_terminate;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (flags & EXTRACT_CUNESCAPE) {
|
||||
bool eight_bit = false;
|
||||
char32_t u;
|
||||
|
||||
r = cunescape_one(*p, (size_t) -1, &u, &eight_bit);
|
||||
if (r < 0) {
|
||||
if (flags & EXTRACT_CUNESCAPE_RELAX) {
|
||||
s[sz++] = '\\';
|
||||
s[sz++] = c;
|
||||
} else
|
||||
return -EINVAL;
|
||||
} else {
|
||||
(*p) += r - 1;
|
||||
|
||||
if (eight_bit)
|
||||
s[sz++] = u;
|
||||
else
|
||||
sz += utf8_encode_unichar(s + sz, u);
|
||||
}
|
||||
} else
|
||||
s[sz++] = c;
|
||||
|
||||
backslash = false;
|
||||
|
||||
} else if (quote) { /* inside either single or double quotes */
|
||||
for (;; (*p)++, c = **p) {
|
||||
if (c == 0) {
|
||||
if (flags & EXTRACT_RELAX)
|
||||
goto finish_force_terminate;
|
||||
return -EINVAL;
|
||||
} else if (c == quote) { /* found the end quote */
|
||||
quote = 0;
|
||||
break;
|
||||
} else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) {
|
||||
backslash = true;
|
||||
break;
|
||||
} else {
|
||||
if (!GREEDY_REALLOC(s, allocated, sz+2))
|
||||
return -ENOMEM;
|
||||
|
||||
s[sz++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
for (;; (*p)++, c = **p) {
|
||||
if (c == 0)
|
||||
goto finish_force_terminate;
|
||||
else if ((c == '\'' || c == '"') && (flags & EXTRACT_QUOTES)) {
|
||||
quote = c;
|
||||
break;
|
||||
} else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) {
|
||||
backslash = true;
|
||||
break;
|
||||
} else if (strchr(separators, c)) {
|
||||
if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
|
||||
(*p)++;
|
||||
goto finish_force_next;
|
||||
}
|
||||
/* Skip additional coalesced separators. */
|
||||
for (;; (*p)++, c = **p) {
|
||||
if (c == 0)
|
||||
goto finish_force_terminate;
|
||||
if (!strchr(separators, c))
|
||||
break;
|
||||
}
|
||||
goto finish;
|
||||
|
||||
} else {
|
||||
if (!GREEDY_REALLOC(s, allocated, sz+2))
|
||||
return -ENOMEM;
|
||||
|
||||
s[sz++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finish_force_terminate:
|
||||
*p = NULL;
|
||||
finish:
|
||||
if (!s) {
|
||||
*p = NULL;
|
||||
*ret = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
finish_force_next:
|
||||
s[sz] = 0;
|
||||
*ret = s;
|
||||
s = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
int extract_first_word_and_warn(
|
||||
const char **p,
|
||||
char **ret,
|
||||
const char *separators,
|
||||
ExtractFlags flags,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *rvalue) {
|
||||
|
||||
/* Try to unquote it, if it fails, warn about it and try again
|
||||
* but this time using EXTRACT_CUNESCAPE_RELAX to keep the
|
||||
* backslashes verbatim in invalid escape sequences. */
|
||||
|
||||
const char *save;
|
||||
int r;
|
||||
|
||||
save = *p;
|
||||
r = extract_first_word(p, ret, separators, flags);
|
||||
if (r >= 0)
|
||||
return r;
|
||||
|
||||
if (r == -EINVAL && !(flags & EXTRACT_CUNESCAPE_RELAX)) {
|
||||
|
||||
/* Retry it with EXTRACT_CUNESCAPE_RELAX. */
|
||||
*p = save;
|
||||
r = extract_first_word(p, ret, separators, flags|EXTRACT_CUNESCAPE_RELAX);
|
||||
if (r >= 0) {
|
||||
/* It worked this time, hence it must have been an invalid escape sequence we could correct. */
|
||||
log_syntax(unit, LOG_WARNING, filename, line, EINVAL, "Invalid escape sequences in line, correcting: \"%s\"", rvalue);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* If it's still EINVAL; then it must be unbalanced quoting, report this. */
|
||||
if (r == -EINVAL)
|
||||
return log_syntax(unit, LOG_ERR, filename, line, r, "Unbalanced quoting, ignoring: \"%s\"", rvalue);
|
||||
}
|
||||
|
||||
/* Can be any error, report it */
|
||||
return log_syntax(unit, LOG_ERR, filename, line, r, "Unable to decode word \"%s\", ignoring: %m", rvalue);
|
||||
}
|
||||
|
||||
int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) {
|
||||
va_list ap;
|
||||
char **l;
|
||||
int n = 0, i, c, r;
|
||||
|
||||
/* Parses a number of words from a string, stripping any
|
||||
* quotes if necessary. */
|
||||
|
||||
assert(p);
|
||||
|
||||
/* Count how many words are expected */
|
||||
va_start(ap, flags);
|
||||
for (;;) {
|
||||
if (!va_arg(ap, char **))
|
||||
break;
|
||||
n++;
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
if (n <= 0)
|
||||
return 0;
|
||||
|
||||
/* Read all words into a temporary array */
|
||||
l = newa0(char*, n);
|
||||
for (c = 0; c < n; c++) {
|
||||
|
||||
r = extract_first_word(p, &l[c], separators, flags);
|
||||
if (r < 0) {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < c; j++)
|
||||
free(l[j]);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
if (r == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we managed to parse all words, return them in the passed
|
||||
* in parameters */
|
||||
va_start(ap, flags);
|
||||
for (i = 0; i < n; i++) {
|
||||
char **v;
|
||||
|
||||
v = va_arg(ap, char **);
|
||||
assert(v);
|
||||
|
||||
*v = l[i];
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
return c;
|
||||
}
|
||||
#endif /* NM_IGNORED */
|
||||
35
src/systemd/src/basic/extract-word.h
Normal file
35
src/systemd/src/basic/extract-word.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2010 Lennart Poettering
|
||||
|
||||
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
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include "macro.h"
|
||||
|
||||
typedef enum ExtractFlags {
|
||||
EXTRACT_RELAX = 1,
|
||||
EXTRACT_CUNESCAPE = 2,
|
||||
EXTRACT_CUNESCAPE_RELAX = 4,
|
||||
EXTRACT_QUOTES = 8,
|
||||
EXTRACT_DONT_COALESCE_SEPARATORS = 16,
|
||||
EXTRACT_RETAIN_ESCAPE = 32,
|
||||
} ExtractFlags;
|
||||
|
||||
int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags);
|
||||
int extract_first_word_and_warn(const char **p, char **ret, const char *separators, ExtractFlags flags, const char *unit, const char *filename, unsigned line, const char *rvalue);
|
||||
int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) _sentinel_;
|
||||
|
|
@ -27,6 +27,7 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "fd-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "macro.h"
|
||||
#if 0 /* NM_IGNORED */
|
||||
#include "missing.h"
|
||||
|
|
@ -34,6 +35,7 @@
|
|||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "util.h"
|
||||
|
||||
int close_nointr(int fd) {
|
||||
|
|
@ -234,7 +236,7 @@ int close_all_fds(const int except[], unsigned n_except) {
|
|||
while ((de = readdir(d))) {
|
||||
int fd = -1;
|
||||
|
||||
if (hidden_file(de->d_name))
|
||||
if (hidden_or_backup_file(de->d_name))
|
||||
continue;
|
||||
|
||||
if (safe_atoi(de->d_name, &fd) < 0)
|
||||
|
|
@ -362,3 +364,17 @@ bool fdname_is_valid(const char *s) {
|
|||
|
||||
return p - s < 256;
|
||||
}
|
||||
|
||||
int fd_get_path(int fd, char **ret) {
|
||||
char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
|
||||
int r;
|
||||
|
||||
xsprintf(procfs_path, "/proc/self/fd/%i", fd);
|
||||
|
||||
r = readlink_malloc(procfs_path, ret);
|
||||
|
||||
if (r == -ENOENT) /* If the file doesn't exist the fd is invalid */
|
||||
return -EBADF;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ void cmsg_close_all(struct msghdr *mh);
|
|||
|
||||
bool fdname_is_valid(const char *s);
|
||||
|
||||
int fd_get_path(int fd, char **ret);
|
||||
|
||||
/* 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)
|
||||
|
|
|
|||
|
|
@ -1087,30 +1087,6 @@ int mkostemp_safe(char *pattern, int flags) {
|
|||
return fd;
|
||||
}
|
||||
|
||||
int open_tmpfile(const char *path, int flags) {
|
||||
char *p;
|
||||
int fd;
|
||||
|
||||
assert(path);
|
||||
|
||||
#ifdef O_TMPFILE
|
||||
/* Try O_TMPFILE first, if it is supported */
|
||||
fd = open(path, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
|
||||
if (fd >= 0)
|
||||
return fd;
|
||||
#endif
|
||||
|
||||
/* Fall back to unguessable name + unlinking */
|
||||
p = strjoina(path, "/systemd-tmp-XXXXXX");
|
||||
|
||||
fd = mkostemp_safe(p, flags);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
unlink(p);
|
||||
return fd;
|
||||
}
|
||||
|
||||
int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
|
||||
const char *fn;
|
||||
char *t;
|
||||
|
|
@ -1234,7 +1210,6 @@ int write_timestamp_file_atomic(const char *fn, usec_t n) {
|
|||
|
||||
return write_string_file(fn, ln, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
|
||||
}
|
||||
#endif /* NM_IGNORED */
|
||||
|
||||
int read_timestamp_file(const char *fn, usec_t *ret) {
|
||||
_cleanup_free_ char *ln = NULL;
|
||||
|
|
@ -1255,6 +1230,7 @@ int read_timestamp_file(const char *fn, usec_t *ret) {
|
|||
*ret = (usec_t) t;
|
||||
return 0;
|
||||
}
|
||||
#endif /* NM_IGNORED */
|
||||
|
||||
int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space) {
|
||||
int r;
|
||||
|
|
@ -1284,3 +1260,105 @@ int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space)
|
|||
|
||||
return fputs(s, f);
|
||||
}
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
int open_tmpfile_unlinkable(const char *directory, int flags) {
|
||||
char *p;
|
||||
int fd;
|
||||
|
||||
assert(directory);
|
||||
|
||||
/* Returns an unlinked temporary file that cannot be linked into the file system anymore */
|
||||
|
||||
#ifdef O_TMPFILE
|
||||
/* Try O_TMPFILE first, if it is supported */
|
||||
fd = open(directory, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
|
||||
if (fd >= 0)
|
||||
return fd;
|
||||
#endif
|
||||
|
||||
/* Fall back to unguessable name + unlinking */
|
||||
p = strjoina(directory, "/systemd-tmp-XXXXXX");
|
||||
|
||||
fd = mkostemp_safe(p, flags);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
(void) unlink(p);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int open_tmpfile_linkable(const char *target, int flags, char **ret_path) {
|
||||
_cleanup_free_ char *tmp = NULL;
|
||||
int r, fd;
|
||||
|
||||
assert(target);
|
||||
assert(ret_path);
|
||||
|
||||
/* Don't allow O_EXCL, as that has a special meaning for O_TMPFILE */
|
||||
assert((flags & O_EXCL) == 0);
|
||||
|
||||
/* Creates a temporary file, that shall be renamed to "target" later. If possible, this uses O_TMPFILE – 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. */
|
||||
|
||||
#ifdef O_TMPFILE
|
||||
{
|
||||
_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);
|
||||
}
|
||||
#endif
|
||||
|
||||
r = tempfn_random(target, NULL, &tmp);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
fd = open(tmp, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|flags, 0640);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
*ret_path = tmp;
|
||||
tmp = NULL;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int link_tmpfile(int fd, const char *path, const char *target) {
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(target);
|
||||
|
||||
/* Moves a temporary file created with open_tmpfile() above into its final place. if "path" is NULL an fd
|
||||
* created with O_TMPFILE is assumed, and linkat() is used. Otherwise it is assumed O_TMPFILE is not supported
|
||||
* on the directory, and renameat2() is used instead.
|
||||
*
|
||||
* Note that in both cases we will not replace existing files. This is because linkat() does not support this
|
||||
* operation currently (renameat2() does), and there is no nice way to emulate this. */
|
||||
|
||||
if (path) {
|
||||
if (rename_noreplace(AT_FDCWD, path, AT_FDCWD, target) < 0)
|
||||
return -errno;
|
||||
} else {
|
||||
char proc_fd_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
|
||||
|
||||
xsprintf(proc_fd_path, "/proc/self/fd/%i", fd);
|
||||
|
||||
if (linkat(AT_FDCWD, proc_fd_path, AT_FDCWD, target, AT_SYMLINK_FOLLOW) < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* NM_IGNORED */
|
||||
|
|
|
|||
|
|
@ -72,7 +72,6 @@ int fflush_and_check(FILE *f);
|
|||
|
||||
int fopen_temporary(const char *path, FILE **_f, char **_temp_path);
|
||||
int mkostemp_safe(char *pattern, int flags);
|
||||
int open_tmpfile(const char *path, int flags);
|
||||
|
||||
int tempfn_xxxxxx(const char *p, const char *extra, char **ret);
|
||||
int tempfn_random(const char *p, const char *extra, char **ret);
|
||||
|
|
@ -82,3 +81,8 @@ int write_timestamp_file_atomic(const char *fn, usec_t n);
|
|||
int read_timestamp_file(const char *fn, usec_t *ret);
|
||||
|
||||
int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space);
|
||||
|
||||
int open_tmpfile_unlinkable(const char *directory, int flags);
|
||||
int open_tmpfile_linkable(const char *target, int flags, char **ret_path);
|
||||
|
||||
int link_tmpfile(int fd, const char *path, const char *target);
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#endif /* NM_IGNORED */
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "time-util.h"
|
||||
|
|
@ -151,6 +152,7 @@ int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif /* NM_IGNORED */
|
||||
|
||||
int readlinkat_malloc(int fd, const char *p, char **ret) {
|
||||
size_t l = 100;
|
||||
|
|
@ -189,6 +191,7 @@ int readlink_malloc(const char *p, char **ret) {
|
|||
return readlinkat_malloc(AT_FDCWD, p, ret);
|
||||
}
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
int readlink_value(const char *p, char **ret) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
char *value;
|
||||
|
|
@ -504,4 +507,18 @@ int get_files_in_directory(const char *path, char ***list) {
|
|||
|
||||
return n;
|
||||
}
|
||||
|
||||
int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
|
||||
char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
|
||||
int r;
|
||||
|
||||
/* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
|
||||
xsprintf(path, "/proc/self/fd/%i", what);
|
||||
|
||||
r = inotify_add_watch(fd, path, mask);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
return r;
|
||||
}
|
||||
#endif /* NM_IGNORED */
|
||||
|
|
|
|||
|
|
@ -72,3 +72,5 @@ union inotify_event_buffer {
|
|||
struct inotify_event ev;
|
||||
uint8_t raw[INOTIFY_EVENT_MAX];
|
||||
};
|
||||
|
||||
int inotify_add_watch_fd(int fd, int what, uint32_t mask);
|
||||
|
|
|
|||
|
|
@ -1777,20 +1777,18 @@ int set_consume(Set *s, void *value) {
|
|||
|
||||
int set_put_strdup(Set *s, const char *p) {
|
||||
char *c;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(p);
|
||||
|
||||
if (set_contains(s, (char*) p))
|
||||
return 0;
|
||||
|
||||
c = strdup(p);
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
|
||||
r = set_consume(s, c);
|
||||
if (r == -EEXIST)
|
||||
return 0;
|
||||
|
||||
return r;
|
||||
return set_consume(s, c);
|
||||
}
|
||||
|
||||
int set_put_strdupv(Set *s, char **l) {
|
||||
|
|
|
|||
|
|
@ -35,6 +35,11 @@ int flush_fd(int fd) {
|
|||
.events = POLLIN,
|
||||
};
|
||||
|
||||
/* Read from the specified file descriptor, until POLLIN is not set anymore, throwing away everything
|
||||
* read. Note that some file descriptors (notable IP sockets) will trigger POLLIN even when no data can be read
|
||||
* (due to IP packet checksum mismatches), hence this function is only safe to be non-blocking if the fd used
|
||||
* was set to non-blocking too. */
|
||||
|
||||
for (;;) {
|
||||
char buf[LINE_MAX];
|
||||
ssize_t l;
|
||||
|
|
|
|||
|
|
@ -28,9 +28,7 @@
|
|||
#include <xlocale.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#if 0 /* NM_IGNORED */
|
||||
#include "extract-word.h"
|
||||
#endif /* NM_IGNORED */
|
||||
#include "macro.h"
|
||||
#include "parse-util.h"
|
||||
#include "string-util.h"
|
||||
|
|
|
|||
|
|
@ -34,9 +34,7 @@
|
|||
#undef basename
|
||||
|
||||
#include "alloc-util.h"
|
||||
#if 0 /* NM_IGNORED */
|
||||
#include "extract-word.h"
|
||||
#endif /* NM_IGNORED */
|
||||
#include "fs-util.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
|
|
@ -769,34 +767,53 @@ char *file_in_same_dir(const char *path, const char *filename) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool hidden_file_allow_backup(const char *filename) {
|
||||
bool hidden_or_backup_file(const char *filename) {
|
||||
const char *p;
|
||||
|
||||
assert(filename);
|
||||
|
||||
return
|
||||
filename[0] == '.' ||
|
||||
streq(filename, "lost+found") ||
|
||||
streq(filename, "aquota.user") ||
|
||||
streq(filename, "aquota.group") ||
|
||||
endswith(filename, ".rpmnew") ||
|
||||
endswith(filename, ".rpmsave") ||
|
||||
endswith(filename, ".rpmorig") ||
|
||||
endswith(filename, ".dpkg-old") ||
|
||||
endswith(filename, ".dpkg-new") ||
|
||||
endswith(filename, ".dpkg-tmp") ||
|
||||
endswith(filename, ".dpkg-dist") ||
|
||||
endswith(filename, ".dpkg-bak") ||
|
||||
endswith(filename, ".dpkg-backup") ||
|
||||
endswith(filename, ".dpkg-remove") ||
|
||||
endswith(filename, ".swp");
|
||||
}
|
||||
|
||||
bool hidden_file(const char *filename) {
|
||||
assert(filename);
|
||||
|
||||
if (endswith(filename, "~"))
|
||||
if (filename[0] == '.' ||
|
||||
streq(filename, "lost+found") ||
|
||||
streq(filename, "aquota.user") ||
|
||||
streq(filename, "aquota.group") ||
|
||||
endswith(filename, "~"))
|
||||
return true;
|
||||
|
||||
return hidden_file_allow_backup(filename);
|
||||
p = strrchr(filename, '.');
|
||||
if (!p)
|
||||
return false;
|
||||
|
||||
/* Please, let's not add more entries to the list below. If external projects think it's a good idea to come up
|
||||
* with always new suffixes and that everybody else should just adjust to that, then it really should be on
|
||||
* them. Hence, in future, let's not add any more entries. Instead, let's ask those packages to instead adopt
|
||||
* one of the generic suffixes/prefixes for hidden files or backups, possibly augmented with an additional
|
||||
* string. Specifically: there's now:
|
||||
*
|
||||
* The generic suffixes "~" and ".bak" for backup files
|
||||
* The generic prefix "." for hidden files
|
||||
*
|
||||
* Thus, if a new package manager "foopkg" wants its own set of ".foopkg-new", ".foopkg-old", ".foopkg-dist"
|
||||
* or so registered, let's refuse that and ask them to use ".foopkg.new", ".foopkg.old" or ".foopkg~" instead.
|
||||
*/
|
||||
|
||||
return STR_IN_SET(p + 1,
|
||||
"rpmnew",
|
||||
"rpmsave",
|
||||
"rpmorig",
|
||||
"dpkg-old",
|
||||
"dpkg-new",
|
||||
"dpkg-tmp",
|
||||
"dpkg-dist",
|
||||
"dpkg-bak",
|
||||
"dpkg-backup",
|
||||
"dpkg-remove",
|
||||
"ucf-new",
|
||||
"ucf-old",
|
||||
"ucf-dist",
|
||||
"swp",
|
||||
"bak",
|
||||
"old",
|
||||
"new");
|
||||
}
|
||||
|
||||
bool is_device_path(const char *path) {
|
||||
|
|
|
|||
|
|
@ -122,7 +122,6 @@ bool path_is_safe(const char *p) _pure_;
|
|||
|
||||
char *file_in_same_dir(const char *path, const char *filename);
|
||||
|
||||
bool hidden_file_allow_backup(const char *filename);
|
||||
bool hidden_file(const char *filename) _pure_;
|
||||
bool hidden_or_backup_file(const char *filename) _pure_;
|
||||
|
||||
bool is_device_path(const char *path);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <net/if.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <poll.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
|
@ -48,9 +49,11 @@
|
|||
#include "socket-util.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#if 0 /* NM_IGNORED */
|
||||
#include "user-util.h"
|
||||
#endif /* NM_IGNORED */
|
||||
#include "utf8.h"
|
||||
#include "util.h"
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
|
|
@ -803,6 +806,42 @@ static const char* const ip_tos_table[] = {
|
|||
|
||||
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
|
||||
|
||||
bool ifname_valid(const char *p) {
|
||||
bool numeric = true;
|
||||
|
||||
/* Checks whether a network interface name is valid. This is inspired by dev_valid_name() in the kernel sources
|
||||
* but slightly stricter, as we only allow non-control, non-space ASCII characters in the interface name. We
|
||||
* also don't permit names that only container numbers, to avoid confusion with numeric interface indexes. */
|
||||
|
||||
if (isempty(p))
|
||||
return false;
|
||||
|
||||
if (strlen(p) >= IFNAMSIZ)
|
||||
return false;
|
||||
|
||||
if (STR_IN_SET(p, ".", ".."))
|
||||
return false;
|
||||
|
||||
while (*p) {
|
||||
if ((unsigned char) *p >= 127U)
|
||||
return false;
|
||||
|
||||
if ((unsigned char) *p <= 32U)
|
||||
return false;
|
||||
|
||||
if (*p == ':' || *p == '/')
|
||||
return false;
|
||||
|
||||
numeric = numeric && (*p >= '0' && *p <= '9');
|
||||
p++;
|
||||
}
|
||||
|
||||
if (numeric)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int getpeercred(int fd, struct ucred *ucred) {
|
||||
socklen_t n = sizeof(struct ucred);
|
||||
struct ucred u;
|
||||
|
|
@ -980,3 +1019,42 @@ fallback:
|
|||
|
||||
return (ssize_t) k;
|
||||
}
|
||||
|
||||
int flush_accept(int fd) {
|
||||
|
||||
struct pollfd pollfd = {
|
||||
.fd = fd,
|
||||
.events = POLLIN,
|
||||
};
|
||||
int r;
|
||||
|
||||
|
||||
/* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately closing them. */
|
||||
|
||||
for (;;) {
|
||||
int cfd;
|
||||
|
||||
r = poll(&pollfd, 1, 0);
|
||||
if (r < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
return -errno;
|
||||
|
||||
} else if (r == 0)
|
||||
return 0;
|
||||
|
||||
cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
|
||||
if (cfd < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
if (errno == EAGAIN)
|
||||
return 0;
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
close(cfd);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,6 +123,8 @@ int fd_inc_rcvbuf(int fd, size_t n);
|
|||
int ip_tos_to_string_alloc(int i, char **s);
|
||||
int ip_tos_from_string(const char *s);
|
||||
|
||||
bool ifname_valid(const char *p);
|
||||
|
||||
int getpeercred(int fd, struct ucred *ucred);
|
||||
int getpeersec(int fd, char **ret);
|
||||
|
||||
|
|
@ -135,5 +137,18 @@ int receive_one_fd(int transport_fd, int flags);
|
|||
|
||||
ssize_t next_datagram_size_fd(int fd);
|
||||
|
||||
int flush_accept(int fd);
|
||||
|
||||
#define CMSG_FOREACH(cmsg, mh) \
|
||||
for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg)))
|
||||
|
||||
/* Covers only file system and abstract AF_UNIX socket addresses, but not unnamed socket addresses. */
|
||||
#define SOCKADDR_UN_LEN(sa) \
|
||||
({ \
|
||||
const struct sockaddr_un *_sa = &(sa); \
|
||||
assert(_sa->sun_family == AF_UNIX); \
|
||||
offsetof(struct sockaddr_un, sun_path) + \
|
||||
(_sa->sun_path[0] == 0 ? \
|
||||
1 + strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : \
|
||||
strnlen(_sa->sun_path, sizeof(_sa->sun_path))); \
|
||||
})
|
||||
|
|
|
|||
|
|
@ -28,9 +28,7 @@
|
|||
|
||||
#include "alloc-util.h"
|
||||
#include "escape.h"
|
||||
#if 0 /* NM_IGNORED */
|
||||
#include "extract-word.h"
|
||||
#endif /* NM_IGNORED */
|
||||
#include "fileio.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
|
|
|
|||
|
|
@ -25,9 +25,7 @@
|
|||
#include <stddef.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#if 0 /* NM_IGNORED */
|
||||
#include "extract-word.h"
|
||||
#endif /* NM_IGNORED */
|
||||
#include "macro.h"
|
||||
#include "util.h"
|
||||
|
||||
|
|
@ -82,9 +80,7 @@ static inline bool strv_isempty(char * const *l) {
|
|||
char **strv_split(const char *s, const char *separator);
|
||||
char **strv_split_newlines(const char *s);
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags);
|
||||
#endif /* NM_IGNORED */
|
||||
|
||||
char *strv_join(char **l, const char *separator);
|
||||
char *strv_join_quoted(char **l);
|
||||
|
|
|
|||
|
|
@ -1086,22 +1086,31 @@ bool timezone_is_valid(const char *name) {
|
|||
return true;
|
||||
}
|
||||
|
||||
clockid_t clock_boottime_or_monotonic(void) {
|
||||
static clockid_t clock = -1;
|
||||
int fd;
|
||||
bool clock_boottime_supported(void) {
|
||||
static int supported = -1;
|
||||
|
||||
if (clock != -1)
|
||||
return clock;
|
||||
/* Note that this checks whether CLOCK_BOOTTIME is available in general as well as available for timerfds()! */
|
||||
|
||||
fd = timerfd_create(CLOCK_BOOTTIME, TFD_NONBLOCK|TFD_CLOEXEC);
|
||||
if (fd < 0)
|
||||
clock = CLOCK_MONOTONIC;
|
||||
else {
|
||||
safe_close(fd);
|
||||
clock = CLOCK_BOOTTIME;
|
||||
if (supported < 0) {
|
||||
int fd;
|
||||
|
||||
fd = timerfd_create(CLOCK_BOOTTIME, TFD_NONBLOCK|TFD_CLOEXEC);
|
||||
if (fd < 0)
|
||||
supported = false;
|
||||
else {
|
||||
safe_close(fd);
|
||||
supported = true;
|
||||
}
|
||||
}
|
||||
|
||||
return clock;
|
||||
return supported;
|
||||
}
|
||||
|
||||
clockid_t clock_boottime_or_monotonic(void) {
|
||||
if (clock_boottime_supported())
|
||||
return CLOCK_BOOTTIME;
|
||||
else
|
||||
return CLOCK_MONOTONIC;
|
||||
}
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ bool ntp_synced(void);
|
|||
int get_timezones(char ***l);
|
||||
bool timezone_is_valid(const char *name);
|
||||
|
||||
bool clock_boottime_supported(void);
|
||||
clockid_t clock_boottime_or_monotonic(void);
|
||||
|
||||
#define xstrftime(buf, fmt, tm) \
|
||||
|
|
|
|||
|
|
@ -539,7 +539,7 @@ int on_ac_power(void) {
|
|||
if (!de)
|
||||
break;
|
||||
|
||||
if (hidden_file(de->d_name))
|
||||
if (hidden_or_backup_file(de->d_name))
|
||||
continue;
|
||||
|
||||
device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
||||
|
|
|
|||
|
|
@ -39,6 +39,37 @@
|
|||
#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)
|
||||
|
||||
int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
|
||||
struct duid d;
|
||||
|
||||
assert_cc(sizeof(d.raw) >= MAX_DUID_LEN);
|
||||
if (duid_len > MAX_DUID_LEN)
|
||||
return -EINVAL;
|
||||
|
||||
switch (duid_type) {
|
||||
case DUID_TYPE_LLT:
|
||||
if (duid_len <= sizeof(d.llt))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case DUID_TYPE_EN:
|
||||
if (duid_len != sizeof(d.en))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case DUID_TYPE_LL:
|
||||
if (duid_len <= sizeof(d.ll))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case DUID_TYPE_UUID:
|
||||
if (duid_len != sizeof(d.uuid))
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
/* accept unknown type in order to be forward compatible */
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
|
||||
sd_id128_t machine_id;
|
||||
uint64_t hash;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#include "unaligned.h"
|
||||
|
||||
typedef enum DUIDType {
|
||||
DUID_TYPE_RAW = 0,
|
||||
DUID_TYPE_LLT = 1,
|
||||
DUID_TYPE_EN = 2,
|
||||
DUID_TYPE_LL = 3,
|
||||
|
|
@ -40,27 +39,28 @@ typedef enum DUIDType {
|
|||
*/
|
||||
#define MAX_DUID_LEN 128
|
||||
|
||||
/* https://tools.ietf.org/html/rfc3315#section-9.1 */
|
||||
struct duid {
|
||||
be16_t type;
|
||||
union {
|
||||
struct {
|
||||
/* DHCP6_DUID_LLT */
|
||||
/* DUID_TYPE_LLT */
|
||||
uint16_t htype;
|
||||
uint32_t time;
|
||||
uint8_t haddr[0];
|
||||
} _packed_ llt;
|
||||
struct {
|
||||
/* DHCP6_DUID_EN */
|
||||
/* DUID_TYPE_EN */
|
||||
uint32_t pen;
|
||||
uint8_t id[8];
|
||||
} _packed_ en;
|
||||
struct {
|
||||
/* DHCP6_DUID_LL */
|
||||
/* DUID_TYPE_LL */
|
||||
int16_t htype;
|
||||
uint8_t haddr[0];
|
||||
} _packed_ ll;
|
||||
struct {
|
||||
/* DHCP6_DUID_UUID */
|
||||
/* DUID_TYPE_UUID */
|
||||
sd_id128_t uuid;
|
||||
} _packed_ uuid;
|
||||
struct {
|
||||
|
|
@ -69,36 +69,6 @@ struct duid {
|
|||
};
|
||||
} _packed_;
|
||||
|
||||
int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len);
|
||||
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len);
|
||||
int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id);
|
||||
|
||||
static inline int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
|
||||
struct duid d;
|
||||
|
||||
assert(duid_len > 0);
|
||||
|
||||
switch (duid_type) {
|
||||
case DUID_TYPE_LLT:
|
||||
if (duid_len <= sizeof(d.llt))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case DUID_TYPE_EN:
|
||||
if (duid_len != sizeof(d.en))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case DUID_TYPE_LL:
|
||||
if (duid_len <= sizeof(d.ll))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case DUID_TYPE_UUID:
|
||||
if (duid_len != sizeof(d.uuid))
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
if (duid_len > sizeof(d.raw))
|
||||
return -EINVAL;
|
||||
/* accept unknown type in order to be forward compatible */
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "network-internal.h"
|
||||
#include "parse-util.h"
|
||||
#include "siphash24.h"
|
||||
#include "socket-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "utf8.h"
|
||||
|
|
@ -180,58 +181,19 @@ int config_parse_net_condition(const char *unit,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_ifname(const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
char **s = data;
|
||||
_cleanup_free_ char *n = NULL;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
n = strdup(rvalue);
|
||||
if (!n)
|
||||
return log_oom();
|
||||
|
||||
if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(*s);
|
||||
if (*n) {
|
||||
*s = n;
|
||||
n = NULL;
|
||||
} else
|
||||
*s = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_ifnames(const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
int config_parse_ifnames(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
char ***sv = data;
|
||||
const char *word, *state;
|
||||
size_t l;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
|
|
@ -239,22 +201,27 @@ int config_parse_ifnames(const char *unit,
|
|||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
FOREACH_WORD(word, l, rvalue, state) {
|
||||
char *n;
|
||||
for (;;) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
|
||||
n = strndup(word, l);
|
||||
if (!n)
|
||||
return log_oom();
|
||||
r = extract_first_word(&rvalue, &word, NULL, 0);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse interface name list: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
|
||||
free(n);
|
||||
if (!ifname_valid(word)) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not valid or too long, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = strv_consume(sv, n);
|
||||
r = strv_push(sv, word);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
word = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -386,28 +353,28 @@ void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
|
|||
int deserialize_in_addrs(struct in_addr **ret, const char *string) {
|
||||
_cleanup_free_ struct in_addr *addresses = NULL;
|
||||
int size = 0;
|
||||
const char *word, *state;
|
||||
size_t len;
|
||||
|
||||
assert(ret);
|
||||
assert(string);
|
||||
|
||||
FOREACH_WORD(word, len, string, state) {
|
||||
_cleanup_free_ char *addr_str = NULL;
|
||||
for (;;) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
struct in_addr *new_addresses;
|
||||
int r;
|
||||
|
||||
r = extract_first_word(&string, &word, NULL, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
new_addresses = realloc(addresses, (size + 1) * sizeof(struct in_addr));
|
||||
if (!new_addresses)
|
||||
return -ENOMEM;
|
||||
else
|
||||
addresses = new_addresses;
|
||||
|
||||
addr_str = strndup(word, len);
|
||||
if (!addr_str)
|
||||
return -ENOMEM;
|
||||
|
||||
r = inet_pton(AF_INET, addr_str, &(addresses[size]));
|
||||
r = inet_pton(AF_INET, word, &(addresses[size]));
|
||||
if (r <= 0)
|
||||
continue;
|
||||
|
||||
|
|
@ -437,28 +404,28 @@ void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses,
|
|||
int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
|
||||
_cleanup_free_ struct in6_addr *addresses = NULL;
|
||||
int size = 0;
|
||||
const char *word, *state;
|
||||
size_t len;
|
||||
|
||||
assert(ret);
|
||||
assert(string);
|
||||
|
||||
FOREACH_WORD(word, len, string, state) {
|
||||
_cleanup_free_ char *addr_str = NULL;
|
||||
for (;;) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
struct in6_addr *new_addresses;
|
||||
int r;
|
||||
|
||||
r = extract_first_word(&string, &word, NULL, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
new_addresses = realloc(addresses, (size + 1) * sizeof(struct in6_addr));
|
||||
if (!new_addresses)
|
||||
return -ENOMEM;
|
||||
else
|
||||
addresses = new_addresses;
|
||||
|
||||
addr_str = strndup(word, len);
|
||||
if (!addr_str)
|
||||
return -ENOMEM;
|
||||
|
||||
r = inet_pton(AF_INET6, addr_str, &(addresses[size]));
|
||||
r = inet_pton(AF_INET6, word, &(addresses[size]));
|
||||
if (r <= 0)
|
||||
continue;
|
||||
|
||||
|
|
@ -499,29 +466,29 @@ void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, siz
|
|||
int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string) {
|
||||
_cleanup_free_ struct sd_dhcp_route *routes = NULL;
|
||||
size_t size = 0, allocated = 0;
|
||||
const char *word, *state;
|
||||
size_t len;
|
||||
|
||||
assert(ret);
|
||||
assert(ret_size);
|
||||
assert(ret_allocated);
|
||||
assert(string);
|
||||
|
||||
FOREACH_WORD(word, len, string, state) {
|
||||
/* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
|
||||
_cleanup_free_ char* entry = NULL;
|
||||
/* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
|
||||
for (;;) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
char *tok, *tok_end;
|
||||
unsigned n;
|
||||
int r;
|
||||
|
||||
r = extract_first_word(&string, &word, NULL, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
if (!GREEDY_REALLOC(routes, allocated, size + 1))
|
||||
return -ENOMEM;
|
||||
|
||||
entry = strndup(word, len);
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
|
||||
tok = entry;
|
||||
tok = word;
|
||||
|
||||
/* get the subnet */
|
||||
tok_end = strchr(tok, '/');
|
||||
|
|
|
|||
|
|
@ -51,10 +51,6 @@ int config_parse_hwaddr(const char *unit, const char *filename, unsigned line,
|
|||
const char *section, unsigned section_line, const char *lvalue,
|
||||
int ltype, const char *rvalue, void *data, void *userdata);
|
||||
|
||||
int config_parse_ifname(const char *unit, const char *filename, unsigned line,
|
||||
const char *section, unsigned section_line, const char *lvalue,
|
||||
int ltype, const char *rvalue, void *data, void *userdata);
|
||||
|
||||
int config_parse_ifnames(const char *unit, const char *filename, unsigned line,
|
||||
const char *section, unsigned section_line, const char *lvalue,
|
||||
int ltype, const char *rvalue, void *data, void *userdata);
|
||||
|
|
|
|||
|
|
@ -117,14 +117,22 @@ static const uint8_t default_req_opts[] = {
|
|||
SD_DHCP_OPTION_DOMAIN_NAME_SERVER,
|
||||
};
|
||||
|
||||
static int client_receive_message_raw(sd_event_source *s, int fd,
|
||||
uint32_t revents, void *userdata);
|
||||
static int client_receive_message_udp(sd_event_source *s, int fd,
|
||||
uint32_t revents, void *userdata);
|
||||
static int client_receive_message_raw(
|
||||
sd_event_source *s,
|
||||
int fd,
|
||||
uint32_t revents,
|
||||
void *userdata);
|
||||
static int client_receive_message_udp(
|
||||
sd_event_source *s,
|
||||
int fd,
|
||||
uint32_t revents,
|
||||
void *userdata);
|
||||
static void client_stop(sd_dhcp_client *client, int error);
|
||||
|
||||
int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_callback_t cb,
|
||||
void *userdata) {
|
||||
int sd_dhcp_client_set_callback(
|
||||
sd_dhcp_client *client,
|
||||
sd_dhcp_client_callback_t cb,
|
||||
void *userdata) {
|
||||
assert_return(client, -EINVAL);
|
||||
|
||||
client->cb = cb;
|
||||
|
|
@ -173,8 +181,9 @@ int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp_client_set_request_address(sd_dhcp_client *client,
|
||||
const struct in_addr *last_addr) {
|
||||
int sd_dhcp_client_set_request_address(
|
||||
sd_dhcp_client *client,
|
||||
const struct in_addr *last_addr) {
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return (IN_SET(client->state, DHCP_STATE_INIT,
|
||||
DHCP_STATE_STOPPED), -EBUSY);
|
||||
|
|
@ -198,8 +207,12 @@ int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
|
||||
size_t addr_len, uint16_t arp_type) {
|
||||
int sd_dhcp_client_set_mac(
|
||||
sd_dhcp_client *client,
|
||||
const uint8_t *addr,
|
||||
size_t addr_len,
|
||||
uint16_t arp_type) {
|
||||
|
||||
DHCP_CLIENT_DONT_DESTROY(client);
|
||||
bool need_restart = false;
|
||||
|
||||
|
|
@ -236,8 +249,11 @@ int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
|
||||
const uint8_t **data, size_t *data_len) {
|
||||
int sd_dhcp_client_get_client_id(
|
||||
sd_dhcp_client *client,
|
||||
uint8_t *type,
|
||||
const uint8_t **data,
|
||||
size_t *data_len) {
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(type, -EINVAL);
|
||||
|
|
@ -256,8 +272,12 @@ int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
|
||||
const uint8_t *data, size_t data_len) {
|
||||
int sd_dhcp_client_set_client_id(
|
||||
sd_dhcp_client *client,
|
||||
uint8_t type,
|
||||
const uint8_t *data,
|
||||
size_t data_len) {
|
||||
|
||||
DHCP_CLIENT_DONT_DESTROY(client);
|
||||
bool need_restart = false;
|
||||
|
||||
|
|
@ -301,13 +321,32 @@ int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
|
|||
}
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid,
|
||||
uint16_t duid_type, uint8_t *duid, size_t duid_len) {
|
||||
/**
|
||||
* Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
|
||||
* without further modification. Otherwise, if duid_type is supported, DUID
|
||||
* is set based on that type. Otherwise, an error is returned.
|
||||
*/
|
||||
int sd_dhcp_client_set_iaid_duid(
|
||||
sd_dhcp_client *client,
|
||||
uint32_t iaid,
|
||||
uint16_t duid_type,
|
||||
const void *duid,
|
||||
size_t duid_len) {
|
||||
|
||||
DHCP_CLIENT_DONT_DESTROY(client);
|
||||
int r;
|
||||
assert_return(client, -EINVAL);
|
||||
zero(client->client_id);
|
||||
size_t len;
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(duid_len == 0 || duid != NULL, -EINVAL);
|
||||
|
||||
if (duid != NULL) {
|
||||
r = dhcp_validate_duid_len(duid_type, duid_len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
zero(client->client_id);
|
||||
client->client_id.type = 255;
|
||||
|
||||
/* If IAID is not configured, generate it. */
|
||||
|
|
@ -320,22 +359,18 @@ int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid,
|
|||
} else
|
||||
client->client_id.ns.iaid = htobe32(iaid);
|
||||
|
||||
/* If DUID is not configured, generate DUID-EN. */
|
||||
if (duid_len == 0) {
|
||||
r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid,
|
||||
&duid_len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
r = dhcp_validate_duid_len(client->client_id.type, duid_len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (duid != NULL) {
|
||||
client->client_id.ns.duid.type = htobe16(duid_type);
|
||||
memcpy(&client->client_id.ns.duid.raw.data, duid, duid_len);
|
||||
duid_len += sizeof(client->client_id.ns.duid.type);
|
||||
}
|
||||
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;
|
||||
|
||||
client->client_id_len = sizeof(client->client_id.type) + duid_len +
|
||||
client->client_id_len = sizeof(client->client_id.type) + len +
|
||||
sizeof(client->client_id.ns.iaid);
|
||||
|
||||
if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
|
||||
|
|
@ -348,8 +383,10 @@ int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid,
|
|||
}
|
||||
#endif /* NM_IGNORED */
|
||||
|
||||
int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
|
||||
const char *hostname) {
|
||||
int sd_dhcp_client_set_hostname(
|
||||
sd_dhcp_client *client,
|
||||
const char *hostname) {
|
||||
|
||||
char *new_hostname = NULL;
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
|
|
@ -372,8 +409,10 @@ int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client,
|
||||
const char *vci) {
|
||||
int sd_dhcp_client_set_vendor_class_identifier(
|
||||
sd_dhcp_client *client,
|
||||
const char *vci) {
|
||||
|
||||
char *new_vci = NULL;
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
|
|
@ -456,8 +495,13 @@ static void client_stop(sd_dhcp_client *client, int error) {
|
|||
client_initialize(client);
|
||||
}
|
||||
|
||||
static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
|
||||
uint8_t type, size_t *_optlen, size_t *_optoffset) {
|
||||
static int client_message_init(
|
||||
sd_dhcp_client *client,
|
||||
DHCPPacket **ret,
|
||||
uint8_t type,
|
||||
size_t *_optlen,
|
||||
size_t *_optoffset) {
|
||||
|
||||
_cleanup_free_ DHCPPacket *packet = NULL;
|
||||
size_t optlen, optoffset, size;
|
||||
be16_t max_size;
|
||||
|
|
@ -598,8 +642,12 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int client_append_fqdn_option(DHCPMessage *message, size_t optlen, size_t *optoffset,
|
||||
const char *fqdn) {
|
||||
static int client_append_fqdn_option(
|
||||
DHCPMessage *message,
|
||||
size_t optlen,
|
||||
size_t *optoffset,
|
||||
const char *fqdn) {
|
||||
|
||||
uint8_t buffer[3 + DHCP_MAX_FQDN_LENGTH];
|
||||
int r;
|
||||
|
||||
|
|
@ -616,8 +664,11 @@ static int client_append_fqdn_option(DHCPMessage *message, size_t optlen, size_t
|
|||
return r;
|
||||
}
|
||||
|
||||
static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet,
|
||||
size_t len) {
|
||||
static int dhcp_client_send_raw(
|
||||
sd_dhcp_client *client,
|
||||
DHCPPacket *packet,
|
||||
size_t len) {
|
||||
|
||||
dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT,
|
||||
INADDR_BROADCAST, DHCP_PORT_SERVER, len);
|
||||
|
||||
|
|
@ -824,8 +875,11 @@ static int client_send_request(sd_dhcp_client *client) {
|
|||
|
||||
static int client_start(sd_dhcp_client *client);
|
||||
|
||||
static int client_timeout_resend(sd_event_source *s, uint64_t usec,
|
||||
void *userdata) {
|
||||
static int client_timeout_resend(
|
||||
sd_event_source *s,
|
||||
uint64_t usec,
|
||||
void *userdata) {
|
||||
|
||||
sd_dhcp_client *client = userdata;
|
||||
DHCP_CLIENT_DONT_DESTROY(client);
|
||||
usec_t next_timeout = 0;
|
||||
|
|
@ -969,8 +1023,10 @@ error:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int client_initialize_io_events(sd_dhcp_client *client,
|
||||
sd_event_io_handler_t io_callback) {
|
||||
static int client_initialize_io_events(
|
||||
sd_dhcp_client *client,
|
||||
sd_event_io_handler_t io_callback) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(client);
|
||||
|
|
@ -1037,8 +1093,7 @@ error:
|
|||
|
||||
}
|
||||
|
||||
static int client_initialize_events(sd_dhcp_client *client,
|
||||
sd_event_io_handler_t io_callback) {
|
||||
static int client_initialize_events(sd_dhcp_client *client, sd_event_io_handler_t io_callback) {
|
||||
client_initialize_io_events(client, io_callback);
|
||||
client_initialize_time_events(client);
|
||||
|
||||
|
|
@ -1078,8 +1133,7 @@ static int client_start(sd_dhcp_client *client) {
|
|||
return client_start_delayed(client);
|
||||
}
|
||||
|
||||
static int client_timeout_expire(sd_event_source *s, uint64_t usec,
|
||||
void *userdata) {
|
||||
static int client_timeout_expire(sd_event_source *s, uint64_t usec, void *userdata) {
|
||||
sd_dhcp_client *client = userdata;
|
||||
DHCP_CLIENT_DONT_DESTROY(client);
|
||||
|
||||
|
|
@ -1119,8 +1173,7 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata)
|
|||
return client_initialize_events(client, client_receive_message_raw);
|
||||
}
|
||||
|
||||
static int client_timeout_t1(sd_event_source *s, uint64_t usec,
|
||||
void *userdata) {
|
||||
static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) {
|
||||
sd_dhcp_client *client = userdata;
|
||||
DHCP_CLIENT_DONT_DESTROY(client);
|
||||
|
||||
|
|
@ -1130,8 +1183,7 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec,
|
|||
return client_initialize_time_events(client);
|
||||
}
|
||||
|
||||
static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
|
||||
size_t len) {
|
||||
static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_t len) {
|
||||
_cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
|
||||
int r;
|
||||
|
||||
|
|
@ -1182,8 +1234,7 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
|
||||
size_t len) {
|
||||
static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force, size_t len) {
|
||||
int r;
|
||||
|
||||
r = dhcp_option_parse(force, len, NULL, NULL, NULL);
|
||||
|
|
@ -1195,8 +1246,7 @@ static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
|
||||
size_t len) {
|
||||
static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack, size_t len) {
|
||||
_cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
|
||||
_cleanup_free_ char *error_message = NULL;
|
||||
int r;
|
||||
|
|
@ -1424,8 +1474,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
|
||||
int len) {
|
||||
static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, int len) {
|
||||
DHCP_CLIENT_DONT_DESTROY(client);
|
||||
char time_string[FORMAT_TIMESPAN_MAX];
|
||||
int r = 0, notify_event = 0;
|
||||
|
|
@ -1571,8 +1620,12 @@ error:
|
|||
return r;
|
||||
}
|
||||
|
||||
static int client_receive_message_udp(sd_event_source *s, int fd,
|
||||
uint32_t revents, void *userdata) {
|
||||
static int client_receive_message_udp(
|
||||
sd_event_source *s,
|
||||
int fd,
|
||||
uint32_t revents,
|
||||
void *userdata) {
|
||||
|
||||
sd_dhcp_client *client = userdata;
|
||||
_cleanup_free_ DHCPMessage *message = NULL;
|
||||
const struct ether_addr zero_mac = { { 0, 0, 0, 0, 0, 0 } };
|
||||
|
|
@ -1649,8 +1702,12 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
|
|||
return client_handle_message(client, message, len);
|
||||
}
|
||||
|
||||
static int client_receive_message_raw(sd_event_source *s, int fd,
|
||||
uint32_t revents, void *userdata) {
|
||||
static int client_receive_message_raw(
|
||||
sd_event_source *s,
|
||||
int fd,
|
||||
uint32_t revents,
|
||||
void *userdata) {
|
||||
|
||||
sd_dhcp_client *client = userdata;
|
||||
_cleanup_free_ DHCPPacket *packet = NULL;
|
||||
uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
|
||||
|
|
|
|||
|
|
@ -113,7 +113,10 @@ DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int);
|
|||
|
||||
static int client_start(sd_dhcp6_client *client, enum DHCP6State state);
|
||||
|
||||
int sd_dhcp6_client_set_callback(sd_dhcp6_client *client, sd_dhcp6_client_callback_t cb, void *userdata) {
|
||||
int sd_dhcp6_client_set_callback(
|
||||
sd_dhcp6_client *client,
|
||||
sd_dhcp6_client_callback_t cb,
|
||||
void *userdata) {
|
||||
assert_return(client, -EINVAL);
|
||||
|
||||
client->cb = cb;
|
||||
|
|
@ -133,7 +136,10 @@ int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_set_local_address(sd_dhcp6_client *client, const struct in6_addr *local_address) {
|
||||
int sd_dhcp6_client_set_local_address(
|
||||
sd_dhcp6_client *client,
|
||||
const struct in6_addr *local_address) {
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(local_address, -EINVAL);
|
||||
assert_return(in_addr_is_link_local(AF_INET6, (const union in_addr_union *) local_address) > 0, -EINVAL);
|
||||
|
|
@ -182,20 +188,38 @@ static int client_ensure_duid(sd_dhcp6_client *client) {
|
|||
return dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t duid_type,
|
||||
uint8_t *duid, size_t duid_len) {
|
||||
/**
|
||||
* Sets DUID. If duid is non-null, the DUID is set to duid_type + duid
|
||||
* 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(
|
||||
sd_dhcp6_client *client,
|
||||
uint16_t duid_type,
|
||||
const void *duid,
|
||||
size_t duid_len) {
|
||||
|
||||
int r;
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(duid_len == 0 || duid != NULL, -EINVAL);
|
||||
assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
|
||||
|
||||
if (duid_len > 0) {
|
||||
if (duid != NULL) {
|
||||
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 = duid_len + sizeof(client->duid.type);
|
||||
}
|
||||
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;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -431,8 +455,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int client_timeout_t2(sd_event_source *s, uint64_t usec,
|
||||
void *userdata) {
|
||||
static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) {
|
||||
sd_dhcp6_client *client = userdata;
|
||||
|
||||
assert_return(s, -EINVAL);
|
||||
|
|
@ -449,8 +472,7 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int client_timeout_t1(sd_event_source *s, uint64_t usec,
|
||||
void *userdata) {
|
||||
static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) {
|
||||
sd_dhcp6_client *client = userdata;
|
||||
|
||||
assert_return(s, -EINVAL);
|
||||
|
|
@ -467,8 +489,7 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int client_timeout_resend_expire(sd_event_source *s, uint64_t usec,
|
||||
void *userdata) {
|
||||
static int client_timeout_resend_expire(sd_event_source *s, uint64_t usec, void *userdata) {
|
||||
sd_dhcp6_client *client = userdata;
|
||||
DHCP6_CLIENT_DONT_DESTROY(client);
|
||||
enum DHCP6State state;
|
||||
|
|
@ -494,8 +515,7 @@ static usec_t client_timeout_compute_random(usec_t val) {
|
|||
(random_u32() % (2 * USEC_PER_SEC)) * val / 10 / USEC_PER_SEC;
|
||||
}
|
||||
|
||||
static int client_timeout_resend(sd_event_source *s, uint64_t usec,
|
||||
void *userdata) {
|
||||
static int client_timeout_resend(sd_event_source *s, uint64_t usec, void *userdata) {
|
||||
int r = 0;
|
||||
sd_dhcp6_client *client = userdata;
|
||||
usec_t time_now, init_retransmit_time = 0, max_retransmit_time = 0;
|
||||
|
|
@ -662,9 +682,11 @@ static int client_ensure_iaid(sd_dhcp6_client *client) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int client_parse_message(sd_dhcp6_client *client,
|
||||
DHCP6Message *message, size_t len,
|
||||
sd_dhcp6_lease *lease) {
|
||||
static int client_parse_message(
|
||||
sd_dhcp6_client *client,
|
||||
DHCP6Message *message,
|
||||
size_t len,
|
||||
sd_dhcp6_lease *lease) {
|
||||
int r;
|
||||
uint8_t *optval, *option, *id = NULL;
|
||||
uint16_t optcode, status;
|
||||
|
|
|
|||
|
|
@ -1080,6 +1080,10 @@ _public_ int sd_event_add_time(
|
|||
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
|
||||
assert_return(!event_pid_changed(e), -ECHILD);
|
||||
|
||||
if (IN_SET(clock, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM) &&
|
||||
!clock_boottime_supported())
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!callback)
|
||||
callback = time_exit_callback;
|
||||
|
||||
|
|
@ -2537,7 +2541,8 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
|
|||
}
|
||||
|
||||
dual_timestamp_get(&e->timestamp);
|
||||
e->timestamp_boottime = now(clock_boottime_or_monotonic());
|
||||
if (clock_boottime_supported())
|
||||
e->timestamp_boottime = now(CLOCK_BOOTTIME);
|
||||
|
||||
for (i = 0; i < m; i++) {
|
||||
|
||||
|
|
@ -2771,6 +2776,9 @@ _public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) {
|
|||
CLOCK_BOOTTIME,
|
||||
CLOCK_BOOTTIME_ALARM), -EOPNOTSUPP);
|
||||
|
||||
if (IN_SET(clock, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM) && !clock_boottime_supported())
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!dual_timestamp_is_set(&e->timestamp)) {
|
||||
/* Implicitly fall back to now() if we never ran
|
||||
* before and thus have no cached time. */
|
||||
|
|
|
|||
|
|
@ -84,28 +84,57 @@ enum {
|
|||
|
||||
typedef struct sd_dhcp_client sd_dhcp_client;
|
||||
|
||||
typedef void (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event,
|
||||
void *userdata);
|
||||
int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_callback_t cb,
|
||||
void *userdata);
|
||||
typedef void (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, void *userdata);
|
||||
int sd_dhcp_client_set_callback(
|
||||
sd_dhcp_client *client,
|
||||
sd_dhcp_client_callback_t cb,
|
||||
void *userdata);
|
||||
|
||||
int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option);
|
||||
int sd_dhcp_client_set_request_address(sd_dhcp_client *client,
|
||||
const struct in_addr *last_address);
|
||||
int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast);
|
||||
int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index);
|
||||
int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
|
||||
size_t addr_len, uint16_t arp_type);
|
||||
int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
|
||||
const uint8_t *data, size_t data_len);
|
||||
int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid,
|
||||
uint16_t duid_type, uint8_t *duid, size_t duid_len);
|
||||
int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
|
||||
const uint8_t **data, size_t *data_len);
|
||||
int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu);
|
||||
int sd_dhcp_client_set_hostname(sd_dhcp_client *client, const char *hostname);
|
||||
int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client, const char *vci);
|
||||
int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret);
|
||||
int sd_dhcp_client_set_request_option(
|
||||
sd_dhcp_client *client,
|
||||
uint8_t option);
|
||||
int sd_dhcp_client_set_request_address(
|
||||
sd_dhcp_client *client,
|
||||
const struct in_addr *last_address);
|
||||
int sd_dhcp_client_set_request_broadcast(
|
||||
sd_dhcp_client *client,
|
||||
int broadcast);
|
||||
int sd_dhcp_client_set_index(
|
||||
sd_dhcp_client *client,
|
||||
int interface_index);
|
||||
int sd_dhcp_client_set_mac(
|
||||
sd_dhcp_client *client,
|
||||
const uint8_t *addr,
|
||||
size_t addr_len,
|
||||
uint16_t arp_type);
|
||||
int sd_dhcp_client_set_client_id(
|
||||
sd_dhcp_client *client,
|
||||
uint8_t type,
|
||||
const uint8_t *data,
|
||||
size_t data_len);
|
||||
int sd_dhcp_client_set_iaid_duid(
|
||||
sd_dhcp_client *client,
|
||||
uint32_t iaid,
|
||||
uint16_t duid_type,
|
||||
const void *duid,
|
||||
size_t duid_len);
|
||||
int sd_dhcp_client_get_client_id(
|
||||
sd_dhcp_client *client,
|
||||
uint8_t *type,
|
||||
const uint8_t **data,
|
||||
size_t *data_len);
|
||||
int sd_dhcp_client_set_mtu(
|
||||
sd_dhcp_client *client,
|
||||
uint32_t mtu);
|
||||
int sd_dhcp_client_set_hostname(
|
||||
sd_dhcp_client *client,
|
||||
const char *hostname);
|
||||
int sd_dhcp_client_set_vendor_class_identifier(
|
||||
sd_dhcp_client *client,
|
||||
const char *vci);
|
||||
int sd_dhcp_client_get_lease(
|
||||
sd_dhcp_client *client,
|
||||
sd_dhcp_lease **ret);
|
||||
|
||||
int sd_dhcp_client_stop(sd_dhcp_client *client);
|
||||
int sd_dhcp_client_start(sd_dhcp_client *client);
|
||||
|
|
@ -115,7 +144,10 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client);
|
|||
|
||||
int sd_dhcp_client_new(sd_dhcp_client **ret);
|
||||
|
||||
int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, int64_t priority);
|
||||
int sd_dhcp_client_attach_event(
|
||||
sd_dhcp_client *client,
|
||||
sd_event *event,
|
||||
int64_t priority);
|
||||
int sd_dhcp_client_detach_event(sd_dhcp_client *client);
|
||||
sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client);
|
||||
|
||||
|
|
|
|||
|
|
@ -76,29 +76,52 @@ enum {
|
|||
|
||||
typedef struct sd_dhcp6_client sd_dhcp6_client;
|
||||
|
||||
typedef void (*sd_dhcp6_client_callback_t)(sd_dhcp6_client *client, int event,
|
||||
void *userdata);
|
||||
int sd_dhcp6_client_set_callback(sd_dhcp6_client *client,
|
||||
sd_dhcp6_client_callback_t cb, void *userdata);
|
||||
typedef void (*sd_dhcp6_client_callback_t)(sd_dhcp6_client *client, int event, void *userdata);
|
||||
int sd_dhcp6_client_set_callback(
|
||||
sd_dhcp6_client *client,
|
||||
sd_dhcp6_client_callback_t cb,
|
||||
void *userdata);
|
||||
|
||||
int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index);
|
||||
int sd_dhcp6_client_set_local_address(sd_dhcp6_client *client, const struct in6_addr *local_address);
|
||||
int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, const uint8_t *addr,
|
||||
size_t addr_len, uint16_t arp_type);
|
||||
int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t duid_type,
|
||||
uint8_t *duid, size_t duid_len);
|
||||
int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid);
|
||||
int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, int enabled);
|
||||
int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, int *enabled);
|
||||
int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client,
|
||||
uint16_t option);
|
||||
int sd_dhcp6_client_set_index(
|
||||
sd_dhcp6_client *client,
|
||||
int interface_index);
|
||||
int sd_dhcp6_client_set_local_address(
|
||||
sd_dhcp6_client *client,
|
||||
const struct in6_addr *local_address);
|
||||
int sd_dhcp6_client_set_mac(
|
||||
sd_dhcp6_client *client,
|
||||
const uint8_t *addr,
|
||||
size_t addr_len,
|
||||
uint16_t arp_type);
|
||||
int sd_dhcp6_client_set_duid(
|
||||
sd_dhcp6_client *client,
|
||||
uint16_t duid_type,
|
||||
const void *duid,
|
||||
size_t duid_len);
|
||||
int sd_dhcp6_client_set_iaid(
|
||||
sd_dhcp6_client *client,
|
||||
uint32_t iaid);
|
||||
int sd_dhcp6_client_set_information_request(
|
||||
sd_dhcp6_client *client,
|
||||
int enabled);
|
||||
int sd_dhcp6_client_get_information_request(
|
||||
sd_dhcp6_client *client,
|
||||
int *enabled);
|
||||
int sd_dhcp6_client_set_request_option(
|
||||
sd_dhcp6_client *client,
|
||||
uint16_t option);
|
||||
|
||||
int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret);
|
||||
int sd_dhcp6_client_get_lease(
|
||||
sd_dhcp6_client *client,
|
||||
sd_dhcp6_lease **ret);
|
||||
|
||||
int sd_dhcp6_client_stop(sd_dhcp6_client *client);
|
||||
int sd_dhcp6_client_start(sd_dhcp6_client *client);
|
||||
int sd_dhcp6_client_is_running(sd_dhcp6_client *client);
|
||||
int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, int64_t priority);
|
||||
int sd_dhcp6_client_attach_event(
|
||||
sd_dhcp6_client *client,
|
||||
sd_event *event,
|
||||
int64_t priority);
|
||||
int sd_dhcp6_client_detach_event(sd_dhcp6_client *client);
|
||||
sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client);
|
||||
sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue