mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-24 16:00:07 +01:00
systemd: update code from upstream
This is a direct dump from systemd git on 2016-05-12, git commit
42d35e1301928d08dd32ec51f0205252ae658ba5.
======
SYSTEMD_DIR=../systemd
COMMIT=42d35e1301928d08dd32ec51f0205252ae658ba5
(
cd "$SYSTEMD_DIR"
git checkout "$COMMIT"
git reset --hard
git clean -fdx
)
git ls-files :/src/systemd/src/ | xargs -d '\n' rm -f
nm_copy_sd() {
mkdir -p "./src/systemd/$(dirname "$1")"
cp "$SYSTEMD_DIR/$1" "./src/systemd/$1"
}
nm_copy_sd "src/basic/alloc-util.c"
nm_copy_sd "src/basic/alloc-util.h"
nm_copy_sd "src/basic/async.h"
nm_copy_sd "src/basic/escape.c"
nm_copy_sd "src/basic/escape.h"
nm_copy_sd "src/basic/ether-addr-util.c"
nm_copy_sd "src/basic/ether-addr-util.h"
nm_copy_sd "src/basic/extract-word.c"
nm_copy_sd "src/basic/extract-word.h"
nm_copy_sd "src/basic/fileio.c"
nm_copy_sd "src/basic/fileio.h"
nm_copy_sd "src/basic/fd-util.c"
nm_copy_sd "src/basic/fd-util.h"
nm_copy_sd "src/basic/fs-util.c"
nm_copy_sd "src/basic/fs-util.h"
nm_copy_sd "src/basic/hash-funcs.c"
nm_copy_sd "src/basic/hash-funcs.h"
nm_copy_sd "src/basic/hashmap.c"
nm_copy_sd "src/basic/hashmap.h"
nm_copy_sd "src/basic/hexdecoct.c"
nm_copy_sd "src/basic/hexdecoct.h"
nm_copy_sd "src/basic/hostname-util.c"
nm_copy_sd "src/basic/hostname-util.h"
nm_copy_sd "src/basic/in-addr-util.c"
nm_copy_sd "src/basic/in-addr-util.h"
nm_copy_sd "src/basic/io-util.c"
nm_copy_sd "src/basic/io-util.h"
nm_copy_sd "src/basic/list.h"
nm_copy_sd "src/basic/log.h"
nm_copy_sd "src/basic/macro.h"
nm_copy_sd "src/basic/mempool.h"
nm_copy_sd "src/basic/mempool.c"
nm_copy_sd "src/basic/parse-util.c"
nm_copy_sd "src/basic/parse-util.h"
nm_copy_sd "src/basic/path-util.c"
nm_copy_sd "src/basic/path-util.h"
nm_copy_sd "src/basic/prioq.h"
nm_copy_sd "src/basic/prioq.c"
nm_copy_sd "src/basic/random-util.c"
nm_copy_sd "src/basic/random-util.h"
nm_copy_sd "src/basic/refcnt.h"
nm_copy_sd "src/basic/set.h"
nm_copy_sd "src/basic/signal-util.h"
nm_copy_sd "src/basic/siphash24.c"
nm_copy_sd "src/basic/siphash24.h"
nm_copy_sd "src/basic/socket-util.c"
nm_copy_sd "src/basic/socket-util.h"
nm_copy_sd "src/basic/sparse-endian.h"
nm_copy_sd "src/basic/stdio-util.h"
nm_copy_sd "src/basic/string-table.c"
nm_copy_sd "src/basic/string-table.h"
nm_copy_sd "src/basic/string-util.c"
nm_copy_sd "src/basic/string-util.h"
nm_copy_sd "src/basic/strv.c"
nm_copy_sd "src/basic/strv.h"
nm_copy_sd "src/basic/time-util.c"
nm_copy_sd "src/basic/time-util.h"
nm_copy_sd "src/basic/umask-util.h"
nm_copy_sd "src/basic/unaligned.h"
nm_copy_sd "src/basic/utf8.c"
nm_copy_sd "src/basic/utf8.h"
nm_copy_sd "src/basic/util.c"
nm_copy_sd "src/basic/util.h"
nm_copy_sd "src/libsystemd-network/arp-util.c"
nm_copy_sd "src/libsystemd-network/arp-util.h"
nm_copy_sd "src/libsystemd-network/dhcp6-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp6-lease-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp6-network.c"
nm_copy_sd "src/libsystemd-network/dhcp6-option.c"
nm_copy_sd "src/libsystemd-network/dhcp6-protocol.h"
nm_copy_sd "src/libsystemd-network/dhcp-identifier.c"
nm_copy_sd "src/libsystemd-network/dhcp-identifier.h"
nm_copy_sd "src/libsystemd-network/dhcp-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp-lease-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp-network.c"
nm_copy_sd "src/libsystemd-network/dhcp-option.c"
nm_copy_sd "src/libsystemd-network/dhcp-packet.c"
nm_copy_sd "src/libsystemd-network/dhcp-protocol.h"
nm_copy_sd "src/libsystemd-network/lldp-internal.h"
nm_copy_sd "src/libsystemd-network/lldp-neighbor.c"
nm_copy_sd "src/libsystemd-network/lldp-neighbor.h"
nm_copy_sd "src/libsystemd-network/lldp-network.c"
nm_copy_sd "src/libsystemd-network/lldp-network.h"
nm_copy_sd "src/libsystemd-network/network-internal.c"
nm_copy_sd "src/libsystemd-network/network-internal.h"
nm_copy_sd "src/libsystemd-network/sd-dhcp6-client.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp6-lease.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp-client.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp-lease.c"
nm_copy_sd "src/libsystemd-network/sd-ipv4ll.c"
nm_copy_sd "src/libsystemd-network/sd-ipv4acd.c"
nm_copy_sd "src/libsystemd-network/sd-lldp.c"
nm_copy_sd "src/libsystemd/sd-event/sd-event.c"
nm_copy_sd "src/libsystemd/sd-id128/sd-id128.c"
nm_copy_sd "src/shared/dns-domain.c"
nm_copy_sd "src/shared/dns-domain.h"
nm_copy_sd "src/systemd/_sd-common.h"
nm_copy_sd "src/systemd/sd-dhcp6-client.h"
nm_copy_sd "src/systemd/sd-dhcp6-lease.h"
nm_copy_sd "src/systemd/sd-dhcp-client.h"
nm_copy_sd "src/systemd/sd-dhcp-lease.h"
nm_copy_sd "src/systemd/sd-event.h"
nm_copy_sd "src/systemd/sd-ndisc.h"
nm_copy_sd "src/systemd/sd-id128.h"
nm_copy_sd "src/systemd/sd-ipv4acd.h"
nm_copy_sd "src/systemd/sd-ipv4ll.h"
nm_copy_sd "src/systemd/sd-lldp.h"
This commit is contained in:
parent
38abb711f5
commit
b4564eaa66
27 changed files with 998 additions and 320 deletions
298
src/systemd/src/basic/extract-word.c
Normal file
298
src/systemd/src/basic/extract-word.c
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
/***
|
||||
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 <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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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_;
|
||||
|
|
@ -25,11 +25,13 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "fd-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "macro.h"
|
||||
#include "missing.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "util.h"
|
||||
|
||||
int close_nointr(int fd) {
|
||||
|
|
@ -229,7 +231,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)
|
||||
|
|
@ -356,3 +358,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)
|
||||
|
|
|
|||
|
|
@ -1083,30 +1083,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;
|
||||
|
|
@ -1278,3 +1254,103 @@ int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space)
|
|||
|
||||
return fputs(s, f);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "mkdir.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "time-util.h"
|
||||
|
|
@ -493,3 +494,17 @@ 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -1773,20 +1773,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) {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,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;
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ static inline int safe_atoli(const char *s, long int *ret_u) {
|
|||
#if SIZE_MAX == UINT_MAX
|
||||
static inline int safe_atozu(const char *s, size_t *ret_u) {
|
||||
assert_cc(sizeof(size_t) == sizeof(unsigned));
|
||||
return safe_atou(s, ret_u);
|
||||
return safe_atou(s, (unsigned *) ret_u);
|
||||
}
|
||||
#else
|
||||
static inline int safe_atozu(const char *s, size_t *ret_u) {
|
||||
|
|
|
|||
|
|
@ -756,34 +756,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);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <net/if.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <poll.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
|
@ -42,7 +43,9 @@
|
|||
#include "socket-util.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "user-util.h"
|
||||
#include "utf8.h"
|
||||
#include "util.h"
|
||||
|
||||
int socket_address_parse(SocketAddress *a, const char *s) {
|
||||
|
|
@ -794,6 +797,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;
|
||||
|
|
@ -970,3 +1009,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))); \
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1080,22 +1080,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;
|
||||
}
|
||||
|
||||
int get_timezone(char **tz) {
|
||||
|
|
|
|||
|
|
@ -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) \
|
||||
|
|
|
|||
|
|
@ -522,7 +522,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);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,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"
|
||||
|
|
@ -175,58 +176,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);
|
||||
|
|
@ -234,22 +196,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;
|
||||
|
|
@ -380,28 +347,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;
|
||||
|
||||
|
|
@ -431,28 +398,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;
|
||||
|
||||
|
|
@ -493,29 +460,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, '/');
|
||||
|
|
|
|||
|
|
@ -50,10 +50,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);
|
||||
|
|
|
|||
|
|
@ -115,14 +115,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;
|
||||
|
|
@ -171,8 +179,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);
|
||||
|
|
@ -196,8 +205,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;
|
||||
|
||||
|
|
@ -234,8 +247,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);
|
||||
|
|
@ -254,8 +270,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;
|
||||
|
||||
|
|
@ -298,13 +318,32 @@ int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
|
|||
return 0;
|
||||
}
|
||||
|
||||
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. */
|
||||
|
|
@ -317,22 +356,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)) {
|
||||
|
|
@ -344,8 +379,10 @@ int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid,
|
|||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
@ -368,8 +405,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);
|
||||
|
|
@ -452,8 +491,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;
|
||||
|
|
@ -594,8 +638,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;
|
||||
|
||||
|
|
@ -612,8 +660,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);
|
||||
|
||||
|
|
@ -820,8 +871,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;
|
||||
|
|
@ -965,8 +1019,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);
|
||||
|
|
@ -1033,8 +1089,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);
|
||||
|
||||
|
|
@ -1074,8 +1129,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);
|
||||
|
||||
|
|
@ -1115,8 +1169,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);
|
||||
|
||||
|
|
@ -1126,8 +1179,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;
|
||||
|
||||
|
|
@ -1178,8 +1230,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);
|
||||
|
|
@ -1191,8 +1242,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;
|
||||
|
|
@ -1420,8 +1470,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;
|
||||
|
|
@ -1567,8 +1616,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 } };
|
||||
|
|
@ -1645,8 +1698,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))];
|
||||
|
|
|
|||
|
|
@ -111,7 +111,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;
|
||||
|
|
@ -131,7 +134,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);
|
||||
|
|
@ -180,20 +186,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;
|
||||
}
|
||||
|
|
@ -427,8 +451,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);
|
||||
|
|
@ -445,8 +468,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);
|
||||
|
|
@ -463,8 +485,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;
|
||||
|
|
@ -490,8 +511,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;
|
||||
|
|
@ -658,9 +678,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;
|
||||
|
|
|
|||
|
|
@ -1072,6 +1072,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;
|
||||
|
||||
|
|
@ -2527,7 +2531,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++) {
|
||||
|
||||
|
|
@ -2761,6 +2766,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