systemd: merge branch 'systemd'

This commit is contained in:
Beniamino Galvani 2015-07-05 12:04:21 +02:00
commit 2deaa39921
39 changed files with 1888 additions and 2775 deletions

View file

@ -57,6 +57,7 @@ noinst_LTLIBRARIES = \
SYSTEMD_NM_CFLAGS = \
-I$(top_srcdir)/src/systemd/src/systemd \
-I$(top_srcdir)/src/systemd/src/libsystemd-network \
-I$(top_srcdir)/src/systemd/src/basic \
-I$(top_srcdir)/src/systemd/src/shared \
-I$(top_srcdir)/src/systemd
@ -85,30 +86,36 @@ libsystemd_nm_la_SOURCES = \
systemd/src/libsystemd-network/sd-ipv4ll.c \
systemd/src/libsystemd-network/ipv4ll-packet.c \
systemd/src/libsystemd-network/ipv4ll-network.c \
systemd/src/shared/async.h \
systemd/src/shared/time-util.h \
systemd/src/shared/siphash24.h \
systemd/src/shared/time-util.c \
systemd/src/shared/socket-util.h \
systemd/src/shared/sparse-endian.h \
systemd/src/shared/macro.h \
systemd/src/shared/refcnt.h \
systemd/src/shared/util.c \
systemd/src/shared/in-addr-util.c \
systemd/src/shared/siphash24.c \
systemd/src/shared/util.h \
systemd/src/shared/in-addr-util.h \
systemd/src/shared/list.h \
systemd/src/shared/log.h \
systemd/src/shared/fileio.h \
systemd/src/shared/fileio.c \
systemd/src/shared/path-util.c \
systemd/src/shared/path-util.h \
systemd/src/shared/strv.h \
systemd/src/shared/strv.c \
systemd/src/shared/unaligned.h \
systemd/src/shared/utf8.h \
systemd/src/shared/utf8.c \
systemd/src/basic/async.h \
systemd/src/basic/time-util.h \
systemd/src/basic/siphash24.h \
systemd/src/basic/time-util.c \
systemd/src/basic/socket-util.h \
systemd/src/basic/sparse-endian.h \
systemd/src/basic/macro.h \
systemd/src/basic/refcnt.h \
systemd/src/basic/util.c \
systemd/src/basic/in-addr-util.c \
systemd/src/basic/siphash24.c \
systemd/src/basic/util.h \
systemd/src/basic/in-addr-util.h \
systemd/src/basic/list.h \
systemd/src/basic/log.h \
systemd/src/basic/fileio.h \
systemd/src/basic/fileio.c \
systemd/src/basic/path-util.c \
systemd/src/basic/path-util.h \
systemd/src/basic/strv.h \
systemd/src/basic/strv.c \
systemd/src/basic/unaligned.h \
systemd/src/basic/utf8.h \
systemd/src/basic/utf8.c \
systemd/src/basic/hostname-util.h \
systemd/src/basic/hostname-util.c \
systemd/src/basic/random-util.h \
systemd/src/basic/random-util.c \
systemd/src/shared/dns-domain.c \
systemd/src/shared/dns-domain.h \
systemd/src/systemd/sd-dhcp-lease.h \
systemd/src/systemd/sd-dhcp-client.h \
systemd/src/systemd/sd-id128.h \

View file

@ -86,11 +86,11 @@ G_STMT_START { \
} G_STMT_END
#define log_assert_failed_return(text, file, line, func) \
G_STMT_START { \
({ \
log_internal (LOG_DEBUG, 0, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Ignoring.", text, file, line, func); \
g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, text); \
} G_STMT_END
(void) 0; \
})
/*****************************************************************************/

View file

@ -0,0 +1,197 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2015 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 <sys/utsname.h>
#include <ctype.h>
#include "util.h"
#include "hostname-util.h"
bool hostname_is_set(void) {
struct utsname u;
assert_se(uname(&u) >= 0);
if (isempty(u.nodename))
return false;
/* This is the built-in kernel default host name */
if (streq(u.nodename, "(none)"))
return false;
return true;
}
char* gethostname_malloc(void) {
struct utsname u;
assert_se(uname(&u) >= 0);
if (isempty(u.nodename) || streq(u.nodename, "(none)"))
return strdup(u.sysname);
return strdup(u.nodename);
}
static bool hostname_valid_char(char c) {
return
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9') ||
c == '-' ||
c == '_' ||
c == '.';
}
bool hostname_is_valid(const char *s) {
const char *p;
bool dot;
if (isempty(s))
return false;
/* Doesn't accept empty hostnames, hostnames with trailing or
* leading dots, and hostnames with multiple dots in a
* sequence. Also ensures that the length stays below
* HOST_NAME_MAX. */
for (p = s, dot = true; *p; p++) {
if (*p == '.') {
if (dot)
return false;
dot = true;
} else {
if (!hostname_valid_char(*p))
return false;
dot = false;
}
}
if (dot)
return false;
if (p-s > HOST_NAME_MAX)
return false;
return true;
}
char* hostname_cleanup(char *s, bool lowercase) {
char *p, *d;
bool dot;
assert(s);
for (p = s, d = s, dot = true; *p; p++) {
if (*p == '.') {
if (dot)
continue;
*(d++) = '.';
dot = true;
} else if (hostname_valid_char(*p)) {
*(d++) = lowercase ? tolower(*p) : *p;
dot = false;
}
}
if (dot && d > s)
d[-1] = 0;
else
*d = 0;
strshorten(s, HOST_NAME_MAX);
return s;
}
bool is_localhost(const char *hostname) {
assert(hostname);
/* This tries to identify local host and domain names
* described in RFC6761 plus the redhatism of .localdomain */
return streq(hostname, "localhost") ||
streq(hostname, "localhost.") ||
streq(hostname, "localdomain.") ||
streq(hostname, "localdomain") ||
endswith(hostname, ".localhost") ||
endswith(hostname, ".localhost.") ||
endswith(hostname, ".localdomain") ||
endswith(hostname, ".localdomain.");
}
#if 0 /* NM_IGNORED */
int sethostname_idempotent(const char *s) {
char buf[HOST_NAME_MAX + 1] = {};
assert(s);
if (gethostname(buf, sizeof(buf)) < 0)
return -errno;
if (streq(buf, s))
return 0;
if (sethostname(s, strlen(s)) < 0)
return -errno;
return 1;
}
int read_hostname_config(const char *path, char **hostname) {
_cleanup_fclose_ FILE *f = NULL;
char l[LINE_MAX];
char *name = NULL;
assert(path);
assert(hostname);
f = fopen(path, "re");
if (!f)
return -errno;
/* may have comments, ignore them */
FOREACH_LINE(l, f, return -errno) {
truncate_nl(l);
if (l[0] != '\0' && l[0] != '#') {
/* found line with value */
name = hostname_cleanup(l, false);
name = strdup(name);
if (!name)
return -ENOMEM;
break;
}
}
if (!name)
/* no non-empty line found */
return -ENOENT;
*hostname = name;
return 0;
}
#endif /* NM_IGNORED */

View file

@ -0,0 +1,41 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#pragma once
/***
This file is part of systemd.
Copyright 2010-2015 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 <stdbool.h>
#include "macro.h"
bool hostname_is_set(void);
char* gethostname_malloc(void);
bool hostname_is_valid(const char *s) _pure_;
char* hostname_cleanup(char *s, bool lowercase);
bool is_localhost(const char *hostname);
int sethostname_idempotent(const char *s);
int read_hostname_config(const char *path, char **hostname);

View file

@ -30,8 +30,8 @@
#include <sys/signalfd.h>
#include <errno.h>
#include "macro.h"
#include "sd-id128.h"
#include "macro.h"
typedef enum LogTarget{
LOG_TARGET_CONSOLE,
@ -208,8 +208,26 @@ LogTarget log_target_from_string(const char *s) _pure_;
/* Helpers to prepare various fields for structured logging */
#define LOG_MESSAGE(fmt, ...) "MESSAGE=" fmt, ##__VA_ARGS__
#define LOG_MESSAGE_ID(x) "MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(x)
#define LOG_ERRNO(error) "ERRNO=%i", abs(error)
void log_received_signal(int level, const struct signalfd_siginfo *si);
void log_set_upgrade_syslog_to_journal(bool b);
int log_syntax_internal(
const char *unit,
int level,
const char *config_file,
unsigned config_line,
int error,
const char *file,
int line,
const char *func,
const char *format, ...) _printf_(9, 10);
#define log_syntax(unit, level, config_file, config_line, error, ...) \
({ \
int _level = (level), _e = (error); \
(log_get_max_level() >= LOG_PRI(_level)) \
? log_syntax_internal(unit, _level, config_file, config_line, _e, __FILE__, __LINE__, __func__, __VA_ARGS__) \
: -abs(_e); \
})

View file

@ -250,10 +250,20 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
REENABLE_WARNING
#endif
#define assert_log(expr) ((_likely_(expr)) \
? (true) \
: (log_assert_failed_return(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__), false))
#define assert_return(expr, r) \
do { \
if (_unlikely_(!(expr))) { \
log_assert_failed_return(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
if (!assert_log(expr)) \
return (r); \
} while (false)
#define assert_return_errno(expr, r, err) \
do { \
if (!assert_log(expr)) { \
errno = err; \
return (r); \
} \
} while (false)
@ -462,4 +472,7 @@ do { \
} \
struct __useless_struct_to_allow_trailing_semicolon__
#define CMSG_FOREACH(cmsg, mh) \
for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg)))
#include "log.h"

View file

@ -38,6 +38,7 @@
#include "path-util.h"
#if 0 /* NM_IGNORED */
#include "missing.h"
#include "fileio.h"
bool path_is_absolute(const char *p) {
return p[0] == '/';
@ -477,25 +478,83 @@ char* path_join(const char *root, const char *path, const char *rest) {
NULL);
}
int fd_is_mount_point(int fd) {
static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id) {
char path[strlen("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)];
_cleanup_free_ char *fdinfo = NULL;
_cleanup_close_ int subfd = -1;
char *p;
int r;
if ((flags & AT_EMPTY_PATH) && isempty(filename))
xsprintf(path, "/proc/self/fdinfo/%i", fd);
else {
subfd = openat(fd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH);
if (subfd < 0)
return -errno;
xsprintf(path, "/proc/self/fdinfo/%i", subfd);
}
r = read_full_file(path, &fdinfo, NULL);
if (r == -ENOENT) /* The fdinfo directory is a relatively new addition */
return -EOPNOTSUPP;
if (r < 0)
return -errno;
p = startswith(fdinfo, "mnt_id:");
if (!p) {
p = strstr(fdinfo, "\nmnt_id:");
if (!p) /* The mnt_id field is a relatively new addition */
return -EOPNOTSUPP;
p += 8;
}
p += strspn(p, WHITESPACE);
p[strcspn(p, WHITESPACE)] = 0;
return safe_atoi(p, mnt_id);
}
int fd_is_mount_point(int fd, const char *filename, int flags) {
union file_handle_union h = FILE_HANDLE_INIT, h_parent = FILE_HANDLE_INIT;
int mount_id = -1, mount_id_parent = -1;
bool nosupp = false;
bool nosupp = false, check_st_dev = true;
struct stat a, b;
int r;
assert(fd >= 0);
assert(filename);
/* We are not actually interested in the file handles, but
* name_to_handle_at() also passes us the mount ID, hence use
* it but throw the handle away */
/* First we will try the name_to_handle_at() syscall, which
* tells us the mount id and an opaque file "handle". It is
* not supported everywhere though (kernel compile-time
* option, not all file systems are hooked up). If it works
* the mount id is usually good enough to tell us whether
* something is a mount point.
*
* If that didn't work we will try to read the mount id from
* /proc/self/fdinfo/<fd>. This is almost as good as
* name_to_handle_at(), however, does not return the the
* opaque file handle. The opaque file handle is pretty useful
* to detect the root directory, which we should always
* consider a mount point. Hence we use this only as
* fallback. Exporting the mnt_id in fdinfo is a pretty recent
* kernel addition.
*
* As last fallback we do traditional fstat() based st_dev
* comparisons. This is how things were traditionally done,
* but unionfs breaks breaks this since it exposes file
* systems with a variety of st_dev reported. Also, btrfs
* subvolumes have different st_dev, even though they aren't
* real mounts of their own. */
r = name_to_handle_at(fd, "", &h.handle, &mount_id, AT_EMPTY_PATH);
r = name_to_handle_at(fd, filename, &h.handle, &mount_id, flags);
if (r < 0) {
if (errno == ENOSYS)
/* This kernel does not support name_to_handle_at()
* fall back to the traditional stat() logic. */
goto fallback;
* fall back to simpler logic. */
goto fallback_fdinfo;
else if (errno == EOPNOTSUPP)
/* This kernel or file system does not support
* name_to_handle_at(), hence let's see if the
@ -507,13 +566,13 @@ int fd_is_mount_point(int fd) {
return -errno;
}
r = name_to_handle_at(fd, "..", &h_parent.handle, &mount_id_parent, 0);
r = name_to_handle_at(fd, "", &h_parent.handle, &mount_id_parent, AT_EMPTY_PATH);
if (r < 0) {
if (errno == EOPNOTSUPP) {
if (nosupp)
/* Neither parent nor child do name_to_handle_at()?
We have no choice but to fall back. */
goto fallback;
goto fallback_fdinfo;
else
/* The parent can't do name_to_handle_at() but the
* directory we are interested in can?
@ -521,32 +580,59 @@ int fd_is_mount_point(int fd) {
return 1;
} else
return -errno;
} else if (nosupp)
/* The parent can do name_to_handle_at() but the
* directory we are interested in can't? If so, it
* must be a mount point. */
return 1;
else {
/* If the file handle for the directory we are
* interested in and its parent are identical, we
* assume this is the root directory, which is a mount
* point. */
if (h.handle.handle_bytes == h_parent.handle.handle_bytes &&
h.handle.handle_type == h_parent.handle.handle_type &&
memcmp(h.handle.f_handle, h_parent.handle.f_handle, h.handle.handle_bytes) == 0)
return 1;
return mount_id != mount_id_parent;
}
fallback:
r = fstatat(fd, "", &a, AT_EMPTY_PATH);
/* The parent can do name_to_handle_at() but the
* directory we are interested in can't? If so, it
* must be a mount point. */
if (nosupp)
return 1;
/* If the file handle for the directory we are
* interested in and its parent are identical, we
* assume this is the root directory, which is a mount
* point. */
if (h.handle.handle_bytes == h_parent.handle.handle_bytes &&
h.handle.handle_type == h_parent.handle.handle_type &&
memcmp(h.handle.f_handle, h_parent.handle.f_handle, h.handle.handle_bytes) == 0)
return 1;
return mount_id != mount_id_parent;
fallback_fdinfo:
r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id);
if (r == -EOPNOTSUPP)
goto fallback_fstat;
if (r < 0)
return r;
r = fd_fdinfo_mnt_id(fd, "", AT_EMPTY_PATH, &mount_id_parent);
if (r < 0)
return r;
if (mount_id != mount_id_parent)
return 1;
/* Hmm, so, the mount ids are the same. This leaves one
* special case though for the root file system. For that,
* let's see if the parent directory has the same inode as we
* are interested in. Hence, let's also do fstat() checks now,
* too, but avoid the st_dev comparisons, since they aren't
* that useful on unionfs mounts. */
check_st_dev = false;
fallback_fstat:
/* yay for fstatat() taking a different set of flags than the other
* _at() above */
if (flags & AT_SYMLINK_FOLLOW)
flags &= ~AT_SYMLINK_FOLLOW;
else
flags |= AT_SYMLINK_NOFOLLOW;
if (fstatat(fd, filename, &a, flags) < 0)
return -errno;
r = fstatat(fd, "..", &b, 0);
if (r < 0)
if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0)
return -errno;
/* A directory with same device and inode as its parent? Must
@ -555,22 +641,39 @@ fallback:
a.st_ino == b.st_ino)
return 1;
return a.st_dev != b.st_dev;
return check_st_dev && (a.st_dev != b.st_dev);
}
int path_is_mount_point(const char *t, bool allow_symlink) {
/* flags can be AT_SYMLINK_FOLLOW or 0 */
int path_is_mount_point(const char *t, int flags) {
_cleanup_close_ int fd = -1;
_cleanup_free_ char *canonical = NULL, *parent = NULL;
int r;
assert(t);
if (path_equal(t, "/"))
return 1;
fd = openat(AT_FDCWD, t, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|(allow_symlink ? 0 : O_PATH));
/* we need to resolve symlinks manually, we can't just rely on
* fd_is_mount_point() to do that for us; if we have a structure like
* /bin -> /usr/bin/ and /usr is a mount point, then the parent that we
* look at needs to be /usr, not /. */
if (flags & AT_SYMLINK_FOLLOW) {
canonical = canonicalize_file_name(t);
if (!canonical)
return -errno;
}
r = path_get_parent(canonical ?: t, &parent);
if (r < 0)
return r;
fd = openat(AT_FDCWD, parent, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_PATH);
if (fd < 0)
return -errno;
return fd_is_mount_point(fd);
return fd_is_mount_point(fd, basename(canonical ?: t), flags);
}
int path_is_read_only_fs(const char *path) {
@ -721,4 +824,38 @@ int fsck_exists(const char *fstype) {
return 0;
}
char *prefix_root(const char *root, const char *path) {
char *n, *p;
size_t l;
/* If root is passed, prefixes path with it. Otherwise returns
* it as is. */
assert(path);
/* First, drop duplicate prefixing slashes from the path */
while (path[0] == '/' && path[1] == '/')
path++;
if (isempty(root) || path_equal(root, "/"))
return strdup(path);
l = strlen(root) + 1 + strlen(path) + 1;
n = new(char, l);
if (!n)
return NULL;
p = stpcpy(n, root);
while (p > n && p[-1] == '/')
p--;
if (path[0] != '/')
*(p++) = '/';
strcpy(p, path);
return n;
}
#endif /* NM_IGNORED */

View file

@ -55,8 +55,8 @@ char** path_strv_make_absolute_cwd(char **l);
char** path_strv_resolve(char **l, const char *prefix);
char** path_strv_resolve_uniq(char **l, const char *prefix);
int fd_is_mount_point(int fd);
int path_is_mount_point(const char *path, bool allow_symlink);
int fd_is_mount_point(int fd, const char *filename, int flags);
int path_is_mount_point(const char *path, int flags);
int path_is_read_only_fs(const char *path);
int path_is_os_tree(const char *path);
@ -75,3 +75,30 @@ int fsck_exists(const char *fstype);
/* Same as PATH_FOREACH_PREFIX but also includes the specified path itself */
#define PATH_FOREACH_PREFIX_MORE(prefix, path) \
for (char *_slash = ({ path_kill_slashes(strcpy(prefix, path)); if (streq(prefix, "/")) prefix[0] = 0; strrchr(prefix, 0); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/'))
char *prefix_root(const char *root, const char *path);
/* Similar to prefix_root(), but returns an alloca() buffer, or
* possibly a const pointer into the path parameter */
#define prefix_roota(root, path) \
({ \
const char* _path = (path), *_root = (root), *_ret; \
char *_p, *_n; \
size_t _l; \
while (_path[0] == '/' && _path[1] == '/') \
_path ++; \
if (isempty(_root) || path_equal(_root, "/")) \
_ret = _path; \
else { \
_l = strlen(_root) + 1 + strlen(_path) + 1; \
_n = alloca(_l); \
_p = stpcpy(_n, _root); \
while (_p > _n && _p[-1] == '/') \
_p--; \
if (_path[0] != '/') \
*(_p++) = '/'; \
strcpy(_p, _path); \
_ret = _n; \
} \
_ret; \
})

View file

@ -0,0 +1,137 @@
/***
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 <stdint.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#ifdef HAVE_SYS_AUXV_H
#include <sys/auxv.h>
#endif
#include <linux/random.h>
#include "random-util.h"
#include "time-util.h"
#if 0 /* NM_IGNORED */
#include "missing.h"
#endif
#include "util.h"
int dev_urandom(void *p, size_t n) {
#if 0 /* NM_IGNORED */
static int have_syscall = -1;
_cleanup_close_ int fd = -1;
int r;
/* Gathers some randomness from the kernel. This call will
* never block, and will always return some data from the
* kernel, regardless if the random pool is fully initialized
* or not. It thus makes no guarantee for the quality of the
* returned entropy, but is good enough for or usual usecases
* of seeding the hash functions for hashtable */
/* Use the getrandom() syscall unless we know we don't have
* it, or when the requested size is too large for it. */
if (have_syscall != 0 || (size_t) (int) n != n) {
r = getrandom(p, n, GRND_NONBLOCK);
if (r == (int) n) {
have_syscall = true;
return 0;
}
if (r < 0) {
if (errno == ENOSYS)
/* we lack the syscall, continue with
* reading from /dev/urandom */
have_syscall = false;
else if (errno == EAGAIN)
/* not enough entropy for now. Let's
* remember to use the syscall the
* next time, again, but also read
* from /dev/urandom for now, which
* doesn't care about the current
* amount of entropy. */
have_syscall = true;
else
return -errno;
} else
/* too short read? */
return -ENODATA;
}
#else /* NM_IGNORED */
_cleanup_close_ int fd = -1;
#endif /* NM_IGNORED */
fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (fd < 0)
return errno == ENOENT ? -ENOSYS : -errno;
return loop_read_exact(fd, p, n, true);
}
void initialize_srand(void) {
static bool srand_called = false;
unsigned x;
#ifdef HAVE_SYS_AUXV_H
void *auxv;
#endif
if (srand_called)
return;
x = 0;
#ifdef HAVE_SYS_AUXV_H
/* The kernel provides us with a bit of entropy in auxv, so
* let's try to make use of that to seed the pseudo-random
* generator. It's better than nothing... */
auxv = (void*) getauxval(AT_RANDOM);
if (auxv)
x ^= *(unsigned*) auxv;
#endif
x ^= (unsigned) now(CLOCK_REALTIME);
x ^= (unsigned) gettid();
srand(x);
srand_called = true;
}
void random_bytes(void *p, size_t n) {
uint8_t *q;
int r;
r = dev_urandom(p, n);
if (r >= 0)
return;
/* If some idiot made /dev/urandom unavailable to us, he'll
* get a PRNG instead. */
initialize_srand();
for (q = p; q < (uint8_t*) p + n; q ++)
*q = rand();
}

View file

@ -0,0 +1,40 @@
#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 "nm-sd-adapt.h"
#include <stdint.h>
int dev_urandom(void *p, size_t n);
void random_bytes(void *p, size_t n);
void initialize_srand(void);
static inline uint64_t random_u64(void) {
uint64_t u;
random_bytes(&u, sizeof(u));
return u;
}
static inline uint32_t random_u32(void) {
uint32_t u;
random_bytes(&u, sizeof(u));
return u;
}

View file

@ -68,6 +68,7 @@ typedef enum SocketAddressBindIPv6Only {
#define socket_address_family(a) ((a)->sockaddr.sa.sa_family)
int socket_address_parse(SocketAddress *a, const char *s);
int socket_address_parse_and_warn(SocketAddress *a, const char *s);
int socket_address_parse_netlink(SocketAddress *a, const char *s);
int socket_address_print(const SocketAddress *a, char **p);
int socket_address_verify(const SocketAddress *a) _pure_;
@ -81,6 +82,7 @@ int socket_address_listen(
int backlog,
SocketAddressBindIPv6Only only,
const char *bind_to_device,
bool reuse_port,
bool free_bind,
bool transparent,
mode_t directory_mode,

View file

@ -405,18 +405,21 @@ void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t) {
t->monotonic);
}
void dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
int dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
unsigned long long a, b;
assert(value);
assert(t);
if (sscanf(value, "%llu %llu", &a, &b) != 2)
log_debug("Failed to parse finish timestamp value %s", value);
else {
t->realtime = a;
t->monotonic = b;
if (sscanf(value, "%llu %llu", &a, &b) != 2) {
log_debug("Failed to parse finish timestamp value %s.", value);
return -EINVAL;
}
t->realtime = a;
t->monotonic = b;
return 0;
}
int parse_timestamp(const char *t, usec_t *usec) {

View file

@ -96,7 +96,7 @@ char *format_timestamp_relative(char *buf, size_t l, usec_t t);
char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy);
void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t);
void dual_timestamp_deserialize(const char *value, dual_timestamp *t);
int dual_timestamp_deserialize(const char *value, dual_timestamp *t);
int parse_timestamp(const char *t, usec_t *usec);

View file

@ -54,7 +54,7 @@
#include "utf8.h"
#include "util.h"
static inline bool is_unicode_valid(uint32_t ch) {
bool unichar_is_valid(uint32_t ch) {
if (ch >= 0x110000) /* End of unicode space */
return false;
@ -68,7 +68,7 @@ static inline bool is_unicode_valid(uint32_t ch) {
return true;
}
static bool is_unicode_control(uint32_t ch) {
static bool unichar_is_control(uint32_t ch) {
/*
0 to ' '-1 is the C0 range.
@ -158,7 +158,7 @@ bool utf8_is_printable_newline(const char* str, size_t length, bool newline) {
val = utf8_encoded_to_unichar(p);
if (val < 0 ||
is_unicode_control(val) ||
unichar_is_control(val) ||
(!newline && val == '\n'))
return false;
@ -278,6 +278,7 @@ char *ascii_is_valid(const char *str) {
* occupy.
*/
size_t utf8_encode_unichar(char *out_utf8, uint32_t g) {
if (g < (1 << 7)) {
if (out_utf8)
out_utf8[0] = g & 0x7f;
@ -303,9 +304,9 @@ size_t utf8_encode_unichar(char *out_utf8, uint32_t g) {
out_utf8[3] = 0x80 | (g & 0x3f);
}
return 4;
} else {
return 0;
}
return 0;
}
char *utf16_to_utf8(const void *s, size_t length) {
@ -396,7 +397,7 @@ int utf8_encoded_valid_unichar(const char *str) {
return -EINVAL;
/* check if value has valid range */
if (!is_unicode_valid(unichar))
if (!unichar_is_valid(unichar))
return -EINVAL;
return len;

View file

@ -29,6 +29,8 @@
#define UTF8_REPLACEMENT_CHARACTER "\xef\xbf\xbd"
bool unichar_is_valid(uint32_t c);
const char *utf8_is_valid(const char *s) _pure_;
char *ascii_is_valid(const char *s) _pure_;

File diff suppressed because it is too large Load diff

View file

@ -31,7 +31,6 @@
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sched.h>
#include <limits.h>
#include <sys/types.h>
@ -45,54 +44,14 @@
#include <sys/inotify.h>
#include <sys/statfs.h>
#if 0 /* NM_IGNORED */
#if SIZEOF_PID_T == 4
# define PID_PRI PRIi32
#elif SIZEOF_PID_T == 2
# define PID_PRI PRIi16
#else
# error Unknown pid_t size
#endif
#define PID_FMT "%" PID_PRI
#if SIZEOF_UID_T == 4
# define UID_FMT "%" PRIu32
#elif SIZEOF_UID_T == 2
# define UID_FMT "%" PRIu16
#else
# error Unknown uid_t size
#endif
#if SIZEOF_GID_T == 4
# define GID_FMT "%" PRIu32
#elif SIZEOF_GID_T == 2
# define GID_FMT "%" PRIu16
#else
# error Unknown gid_t size
#endif
#if SIZEOF_TIME_T == 8
# define PRI_TIME PRIi64
#elif SIZEOF_TIME_T == 4
# define PRI_TIME PRIu32
#else
# error Unknown time_t size
#endif
#if SIZEOF_RLIM_T == 8
# define RLIM_FMT "%" PRIu64
#elif SIZEOF_RLIM_T == 4
# define RLIM_FMT "%" PRIu32
#else
# error Unknown rlim_t size
#endif
#endif /* NM_IGNORED */
#include "macro.h"
#if 0 /* NM_IGNORED */
#include "missing.h"
#endif /* NM_IGNORED */
#include "time-util.h"
#if 0 /* NM_IGNORED */
#include "formats-util.h"
#endif /* NM_IGNORED */
/* What is interpreted as whitespace? */
#define WHITESPACE " \t\n\r"
@ -109,16 +68,6 @@
#define FORMAT_BYTES_MAX 8
#define ANSI_HIGHLIGHT_ON "\x1B[1;39m"
#define ANSI_RED_ON "\x1B[31m"
#define ANSI_HIGHLIGHT_RED_ON "\x1B[1;31m"
#define ANSI_GREEN_ON "\x1B[32m"
#define ANSI_HIGHLIGHT_GREEN_ON "\x1B[1;32m"
#define ANSI_HIGHLIGHT_YELLOW_ON "\x1B[1;33m"
#define ANSI_HIGHLIGHT_BLUE_ON "\x1B[1;34m"
#define ANSI_HIGHLIGHT_OFF "\x1B[0m"
#define ANSI_ERASE_TO_END_OF_LINE "\x1B[K"
size_t page_size(void) _pure_;
#define PAGE_ALIGN(l) ALIGN_TO((l), page_size())
@ -190,6 +139,7 @@ static inline char *startswith_no_case(const char *s, const char *prefix) {
}
char *endswith(const char *s, const char *postfix) _pure_;
char *endswith_no_case(const char *s, const char *postfix) _pure_;
char *first_word(const char *s, const char *word) _pure_;
@ -273,23 +223,15 @@ const char* split(const char **state, size_t *l, const char *separator, bool quo
#define _FOREACH_WORD(word, length, s, separator, quoted, state) \
for ((state) = (s), (word) = split(&(state), &(length), (separator), (quoted)); (word); (word) = split(&(state), &(length), (separator), (quoted)))
pid_t get_parent_of_pid(pid_t pid, pid_t *ppid);
char *strappend(const char *s, const char *suffix);
char *strnappend(const char *s, const char *suffix, size_t length);
char *replace_env(const char *format, char **env);
char **replace_env_argv(char **argv, char **env);
int readlinkat_malloc(int fd, const char *p, char **ret);
int readlink_malloc(const char *p, char **r);
int readlink_value(const char *p, char **ret);
int readlink_and_make_absolute(const char *p, char **r);
int readlink_and_canonicalize(const char *p, char **r);
int reset_all_signal_handlers(void);
int reset_signal_mask(void);
char *strstrip(char *s);
char *delete_chars(char *s, const char *bad);
char *truncate_nl(char *s);
@ -298,17 +240,6 @@ char *file_in_same_dir(const char *path, const char *filename);
int rmdir_parents(const char *path, const char *stop);
int get_process_state(pid_t pid);
int get_process_comm(pid_t pid, char **name);
int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line);
int get_process_exe(pid_t pid, char **name);
int get_process_uid(pid_t pid, uid_t *uid);
int get_process_gid(pid_t pid, gid_t *gid);
int get_process_capeff(pid_t pid, char **capeff);
int get_process_cwd(pid_t pid, char **cwd);
int get_process_root(pid_t pid, char **root);
int get_process_environ(pid_t pid, char **environ);
char hexchar(int x) _const_;
int unhexchar(char c) _const_;
char octchar(int x) _const_;
@ -317,6 +248,7 @@ char decchar(int x) _const_;
int undecchar(char c) _const_;
char *cescape(const char *s);
size_t cescape_char(char c, char *buf);
typedef enum UnescapeFlags {
UNESCAPE_RELAX = 1,
@ -337,26 +269,6 @@ bool hidden_file(const char *filename) _pure_;
bool chars_intersect(const char *a, const char *b) _pure_;
int make_stdio(int fd);
int make_null_stdio(void);
int make_console_stdio(void);
int dev_urandom(void *p, size_t n);
void random_bytes(void *p, size_t n);
void initialize_srand(void);
static inline uint64_t random_u64(void) {
uint64_t u;
random_bytes(&u, sizeof(u));
return u;
}
static inline uint32_t random_u32(void) {
uint32_t u;
random_bytes(&u, sizeof(u));
return u;
}
/* For basic lookup tables with strictly enumerated entries */
#define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
scope const char *name##_to_string(type i) { \
@ -422,25 +334,8 @@ int close_all_fds(const int except[], unsigned n_except);
bool fstype_is_network(const char *fstype);
int chvt(int vt);
int read_one_char(FILE *f, char *ret, usec_t timeout, bool *need_nl);
int ask_char(char *ret, const char *replies, const char *text, ...) _printf_(3, 4);
int ask_string(char **ret, const char *text, ...) _printf_(2, 3);
int reset_terminal_fd(int fd, bool switch_to_text);
int reset_terminal(const char *name);
int open_terminal(const char *name, int mode);
int acquire_terminal(const char *name, bool fail, bool force, bool ignore_tiocstty_eperm, usec_t timeout);
int release_terminal(void);
int flush_fd(int fd);
int ignore_signals(int sig, ...);
int default_signals(int sig, ...);
int sigaction_many(const struct sigaction *sa, ...);
int fopen_temporary(const char *path, FILE **_f, char **_temp_path);
ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll);
@ -452,24 +347,10 @@ bool is_device_path(const char *path);
int dir_is_empty(const char *path);
char* dirname_malloc(const char *path);
void rename_process(const char name[8]);
void sigset_add_many(sigset_t *ss, ...);
int sigprocmask_many(int how, ...);
bool hostname_is_set(void);
char* lookup_uid(uid_t uid);
char* gethostname_malloc(void);
char* getlogname_malloc(void);
char* getusername_malloc(void);
int getttyname_malloc(int fd, char **r);
int getttyname_harder(int fd, char **r);
int get_ctty_devnr(pid_t pid, dev_t *d);
int get_ctty(pid_t, dev_t *_devnr, char **r);
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid);
@ -480,43 +361,8 @@ int pipe_eof(int fd);
cpu_set_t* cpu_set_malloc(unsigned *ncpus);
int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) _printf_(4,0);
int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) _printf_(4,5);
#define xsprintf(buf, fmt, ...) assert_se((size_t) snprintf(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__) < ELEMENTSOF(buf))
int fd_columns(int fd);
unsigned columns(void);
int fd_lines(int fd);
unsigned lines(void);
void columns_lines_cache_reset(int _unused_ signum);
bool on_tty(void);
static inline const char *ansi_highlight(void) {
return on_tty() ? ANSI_HIGHLIGHT_ON : "";
}
static inline const char *ansi_highlight_red(void) {
return on_tty() ? ANSI_HIGHLIGHT_RED_ON : "";
}
static inline const char *ansi_highlight_green(void) {
return on_tty() ? ANSI_HIGHLIGHT_GREEN_ON : "";
}
static inline const char *ansi_highlight_yellow(void) {
return on_tty() ? ANSI_HIGHLIGHT_YELLOW_ON : "";
}
static inline const char *ansi_highlight_blue(void) {
return on_tty() ? ANSI_HIGHLIGHT_BLUE_ON : "";
}
static inline const char *ansi_highlight_off(void) {
return on_tty() ? ANSI_HIGHLIGHT_OFF : "";
}
int files_same(const char *filea, const char *fileb);
int running_in_chroot(void);
@ -528,12 +374,6 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode);
int touch(const char *path);
char *unquote(const char *s, const char *quotes);
char *normalize_env_assignment(const char *s);
int wait_for_terminate(pid_t pid, siginfo_t *status);
int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code);
noreturn void freeze(void);
bool null_or_empty(struct stat *st) _pure_;
@ -544,32 +384,17 @@ DIR *xopendirat(int dirfd, const char *name, int flags);
char *fstab_node_to_udev_node(const char *p);
char *resolve_dev_console(char **active);
bool tty_is_vc(const char *tty);
bool tty_is_vc_resolve(const char *tty);
bool tty_is_console(const char *tty) _pure_;
int vtnr_from_tty(const char *tty);
const char *default_term_for_tty(const char *tty);
void execute_directories(const char* const* directories, usec_t timeout, char *argv[]);
int kill_and_sigcont(pid_t pid, int sig);
bool nulstr_contains(const char*nulstr, const char *needle);
bool plymouth_running(void);
bool hostname_is_valid(const char *s) _pure_;
char* hostname_cleanup(char *s, bool lowercase);
bool machine_name_is_valid(const char *s) _pure_;
char* strshorten(char *s, size_t l);
int terminal_vhangup_fd(int fd);
int terminal_vhangup(const char *name);
int vt_disallocate(const char *name);
int symlink_idempotent(const char *from, const char *to);
int symlink_atomic(const char *from, const char *to);
int mknod_atomic(const char *path, mode_t mode, dev_t dev);
@ -635,11 +460,6 @@ int rlimit_from_string(const char *s) _pure_;
int ip_tos_to_string_alloc(int i, char **s);
int ip_tos_from_string(const char *s);
const char *signal_to_string(int i) _const_;
int signal_from_string(const char *s) _pure_;
int signal_from_string_try_harder(const char *s);
extern int saved_argc;
extern char **saved_argv;
@ -653,8 +473,6 @@ int fd_wait_for_event(int fd, int event, usec_t timeout);
void* memdup(const void *p, size_t l) _alloc_(2);
int is_kernel_thread(pid_t pid);
int fd_inc_sndbuf(int fd, size_t n);
int fd_inc_rcvbuf(int fd, size_t n);
@ -662,8 +480,6 @@ int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *pa
int setrlimit_closest(int resource, const struct rlimit *rlim);
int getenv_for_pid(pid_t pid, const char *field, char **_value);
bool http_url_is_valid(const char *url) _pure_;
bool documentation_url_is_valid(const char *url) _pure_;
@ -671,8 +487,6 @@ bool http_etag_is_valid(const char *etag);
bool in_initrd(void);
void warn_melody(void);
int get_home_dir(char **ret);
int get_shell(char **_ret);
@ -940,19 +754,6 @@ int unlink_noerrno(const char *path);
_d_; \
})
#define procfs_file_alloca(pid, field) \
({ \
pid_t _pid_ = (pid); \
const char *_r_; \
if (_pid_ == 0) { \
_r_ = ("/proc/self/" field); \
} else { \
_r_ = alloca(strlen("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \
sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_); \
} \
_r_; \
})
bool id128_is_valid(const char *s) _pure_;
int split_pair(const char *s, const char *sep, char **l, char **r);
@ -963,12 +764,27 @@ int shall_restore_state(void);
* Normal qsort requires base to be nonnull. Here were require
* that only if nmemb > 0.
*/
static inline void qsort_safe(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *)) {
if (nmemb) {
assert(base);
qsort(base, nmemb, size, compar);
}
static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_fn_t compar) {
if (nmemb <= 1)
return;
assert(base);
qsort(base, nmemb, size, compar);
}
/* Normal memmem() requires haystack to be nonnull, which is annoying for zero-length buffers */
static inline void *memmem_safe(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) {
if (needlelen <= 0)
return (void*) haystack;
if (haystacklen < needlelen)
return NULL;
assert(haystack);
assert(needle);
return memmem(haystack, haystacklen, needle, needlelen);
}
int proc_cmdline(char **ret);
@ -980,9 +796,6 @@ int container_get_leader(const char *machine, pid_t *pid);
int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *root_fd);
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int root_fd);
bool pid_is_alive(pid_t pid);
bool pid_is_unwaited(pid_t pid);
#if 0 /* NM_IGNORED */
int getpeercred(int fd, struct ucred *ucred);
int getpeersec(int fd, char **ret);
@ -995,6 +808,13 @@ int open_tmpfile(const char *path, int flags);
int fd_warn_permissions(const char *path, int fd);
#ifndef PERSONALITY_INVALID
/* personality(7) documents that 0xffffffffUL is used for querying the
* current personality, hence let's use that here as error
* indicator. */
#define PERSONALITY_INVALID 0xffffffffLU
#endif
unsigned long personality_from_string(const char *p);
const char *personality_to_string(unsigned long);
@ -1018,29 +838,28 @@ int bind_remount_recursive(const char *prefix, bool ro);
int fflush_and_check(FILE *f);
int tempfn_xxxxxx(const char *p, char **ret);
int tempfn_random(const char *p, char **ret);
int tempfn_random_child(const char *p, char **ret);
bool is_localhost(const char *hostname);
int tempfn_xxxxxx(const char *p, const char *extra, char **ret);
int tempfn_random(const char *p, const char *extra, char **ret);
int tempfn_random_child(const char *p, const char *extra, char **ret);
int take_password_lock(const char *root);
int is_symlink(const char *path);
int is_dir(const char *path, bool follow);
int is_device_node(const char *path);
typedef enum UnquoteFlags {
UNQUOTE_RELAX = 1,
UNQUOTE_CUNESCAPE = 2,
UNQUOTE_RELAX = 1,
UNQUOTE_CUNESCAPE = 2,
UNQUOTE_CUNESCAPE_RELAX = 4,
} UnquoteFlags;
int unquote_first_word(const char **p, char **ret, UnquoteFlags flags);
int unquote_first_word_and_warn(const char **p, char **ret, UnquoteFlags flags, const char *unit, const char *filename, unsigned line, const char *rvalue);
int unquote_many_words(const char **p, UnquoteFlags flags, ...) _sentinel_;
int free_and_strdup(char **p, const char *s);
int sethostname_idempotent(const char *s);
#define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1)
#define FOREACH_INOTIFY_EVENT(e, buffer, sz) \
@ -1068,27 +887,12 @@ int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags);
int same_fd(int a, int b);
int chattr_fd(int fd, bool b, unsigned mask);
int chattr_path(const char *p, bool b, unsigned mask);
int change_attr_fd(int fd, unsigned value, unsigned mask);
int chattr_fd(int fd, unsigned value, unsigned mask);
int chattr_path(const char *p, unsigned value, unsigned mask);
int read_attr_fd(int fd, unsigned *ret);
int read_attr_path(const char *p, unsigned *ret);
typedef struct LockFile {
char *path;
int fd;
int operation;
} LockFile;
int make_lock_file(const char *p, int operation, LockFile *ret);
int make_lock_file_for(const char *p, int operation, LockFile *ret);
void release_lock_file(LockFile *f);
#define _cleanup_release_lock_file_ _cleanup_(release_lock_file)
#define LOCK_FILE_INIT { .fd = -1, .path = NULL }
#define RLIMIT_MAKE_CONST(lim) ((struct rlimit) { lim, lim })
ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length);
@ -1101,3 +905,11 @@ int syslog_parse_priority(const char **p, int *priority, bool with_facility);
void cmsg_close_all(struct msghdr *mh);
int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
char *shell_maybe_quote(const char *s);
int parse_mode(const char *s, mode_t *ret);
int mount_move_root(const char *path);
int reset_uid_gid(void);

View file

@ -22,7 +22,7 @@
#include "nm-sd-adapt.h"
#include "sd-id128.h"
#if 0 /* NM_IGNORED a*/
#if 0 /* NM_IGNORED */
#include "libudev.h"
#include "udev-util.h"
@ -51,8 +51,9 @@ int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
if (r < 0)
return r;
duid->type = htobe16(DHCP6_DUID_EN);
duid->en.pen = htobe32(SYSTEMD_PEN);
unaligned_write_be16(&duid->type, DHCP6_DUID_EN);
unaligned_write_be32(&duid->en.pen, SYSTEMD_PEN);
*len = sizeof(duid->type) + sizeof(duid->en);
/* a bit of snake-oil perhaps, but no need to expose the machine-id
@ -63,7 +64,7 @@ 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, uint32_t *_id) {
int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id) {
#if 0 /* NM_IGNORED */
/* name is a pointer to memory in the udev_device struct, so must
have the same scope */
@ -105,7 +106,7 @@ int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, uint32_t
siphash24((uint8_t*)&id, mac, mac_len, HASH_KEY.bytes);
/* fold into 32 bits */
*_id = (id & 0xffffffff) ^ (id >> 32);
unaligned_write_be32(_id, (id & 0xffffffff) ^ (id >> 32));
return 0;
}

View file

@ -25,6 +25,7 @@
#include "macro.h"
#include "sparse-endian.h"
#include "unaligned.h"
#include "sd-id128.h"
/* RFC 3315 section 9.1:
@ -62,4 +63,4 @@ struct duid {
} _packed_;
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, uint32_t *_id);
int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id);

View file

@ -30,6 +30,7 @@
#include "util.h"
#include "refcnt.h"
#include "random-util.h"
#include "async.h"
#include "dhcp-protocol.h"
@ -39,7 +40,7 @@
#include "sd-dhcp-client.h"
#define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
#define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
struct sd_dhcp_client {
RefCount n_ref;
@ -929,6 +930,8 @@ static int client_initialize_time_events(sd_dhcp_client *client) {
r = sd_event_source_set_priority(client->timeout_resend,
client->event_priority);
if (r < 0)
goto error;
r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
if (r < 0)
@ -1471,7 +1474,7 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
_cleanup_free_ DHCPMessage *message = NULL;
int buflen = 0, len, r;
const struct ether_addr zero_mac = { { 0, 0, 0, 0, 0, 0 } };
bool expect_chaddr;
const struct ether_addr *expected_chaddr = NULL;
uint8_t expected_hlen = 0;
assert(s);
@ -1516,11 +1519,11 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
if (client->arp_type == ARPHRD_ETHER) {
expected_hlen = ETH_ALEN;
expect_chaddr = true;
expected_chaddr = (const struct ether_addr *) &client->mac_addr;
} else {
/* Non-ethernet links expect zero chaddr */
expected_hlen = 0;
expect_chaddr = false;
expected_chaddr = &zero_mac;
}
if (message->hlen != expected_hlen) {
@ -1528,10 +1531,7 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
return 0;
}
if (memcmp(&message->chaddr[0], expect_chaddr ?
(void *)&client->mac_addr :
(void *)&zero_mac,
ETH_ALEN)) {
if (memcmp(&message->chaddr[0], expected_chaddr, ETH_ALEN)) {
log_dhcp_client(client, "received chaddr does not match "
"expected: ignoring");
return 0;
@ -1592,7 +1592,7 @@ static int client_receive_message_raw(sd_event_source *s, int fd,
} else if ((size_t)len < sizeof(DHCPPacket))
return 0;
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
CMSG_FOREACH(cmsg, &msg) {
if (cmsg->cmsg_level == SOL_PACKET &&
cmsg->cmsg_type == PACKET_AUXDATA &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) {

View file

@ -29,11 +29,12 @@
#include "fileio.h"
#include "unaligned.h"
#include "in-addr-util.h"
#include "hostname-util.h"
#include "dhcp-protocol.h"
#include "dhcp-lease-internal.h"
#include "sd-dhcp-lease.h"
#include "network-internal.h"
#include "dns-domain.h"
int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) {
assert_return(lease, -EINVAL);
@ -537,9 +538,18 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
if (e)
*e = 0;
if (!hostname_is_valid(domainname) || is_localhost(domainname))
if (is_localhost(domainname))
break;
r = dns_name_is_valid(domainname);
if (r <= 0) {
if (r < 0)
log_error_errno(r, "Failed to validate domain name: %s: %m", domainname);
if (r == 0)
log_warning("Domain name is not valid, ignoring: %s", domainname);
break;
}
free(lease->domainname);
lease->domainname = domainname;
domainname = NULL;
@ -726,7 +736,7 @@ int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
if (r >= 0) {
_cleanup_free_ char *client_id_hex = NULL;
client_id_hex = hexmem (client_id, client_id_len);
client_id_hex = hexmem(client_id, client_id_len);
if (!client_id_hex) {
r = -ENOMEM;
goto finish;

View file

@ -32,6 +32,7 @@
#endif /* NM_IGNORED */
#include "util.h"
#include "refcnt.h"
#include "random-util.h"
#include "network-internal.h"
#include "sd-dhcp6-client.h"
@ -1208,6 +1209,7 @@ sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) {
client_reset(client);
sd_dhcp6_client_detach_event(client);
sd_dhcp6_lease_unref(client->lease);
free(client->req_opts);
free(client);

View file

@ -29,6 +29,7 @@
#include "siphash24.h"
#include "list.h"
#include "refcnt.h"
#include "random-util.h"
#include "ipv4ll-internal.h"
#include "sd-ipv4ll.h"

View file

@ -28,6 +28,7 @@
#include "util.h"
#include "macro.h"
#include "sd-id128.h"
#include "random-util.h"
#if 0 /* NM_IGNORED */
_public_ char *sd_id128_to_string(sd_id128_t id, char s[33]) {

View file

@ -0,0 +1,617 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2014 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"
#ifdef HAVE_LIBIDN
#include <idna.h>
#include <stringprep.h>
#endif
#include "dns-domain.h"
int dns_label_unescape(const char **name, char *dest, size_t sz) {
const char *n;
char *d;
int r = 0;
assert(name);
assert(*name);
assert(dest);
n = *name;
d = dest;
for (;;) {
if (*n == '.') {
n++;
break;
}
if (*n == 0)
break;
if (sz <= 0)
return -ENOSPC;
if (r >= DNS_LABEL_MAX)
return -EINVAL;
if (*n == '\\') {
/* Escaped character */
n++;
if (*n == 0)
/* Ending NUL */
return -EINVAL;
else if (*n == '\\' || *n == '.') {
/* Escaped backslash or dot */
*(d++) = *(n++);
sz--;
r++;
} else if (n[0] >= '0' && n[0] <= '9') {
unsigned k;
/* Escaped literal ASCII character */
if (!(n[1] >= '0' && n[1] <= '9') ||
!(n[2] >= '0' && n[2] <= '9'))
return -EINVAL;
k = ((unsigned) (n[0] - '0') * 100) +
((unsigned) (n[1] - '0') * 10) +
((unsigned) (n[2] - '0'));
/* Don't allow CC characters or anything that doesn't fit in 8bit */
if (k < ' ' || k > 255 || k == 127)
return -EINVAL;
*(d++) = (char) k;
sz--;
r++;
n += 3;
} else
return -EINVAL;
} else if ((uint8_t) *n >= (uint8_t) ' ' && *n != 127) {
/* Normal character */
*(d++) = *(n++);
sz--;
r++;
} else
return -EINVAL;
}
/* Empty label that is not at the end? */
if (r == 0 && *n)
return -EINVAL;
if (sz >= 1)
*d = 0;
*name = n;
return r;
}
int dns_label_escape(const char *p, size_t l, char **ret) {
_cleanup_free_ char *s = NULL;
char *q;
int r;
assert(p);
assert(ret);
if (l > DNS_LABEL_MAX)
return -EINVAL;
s = malloc(l * 4 + 1);
if (!s)
return -ENOMEM;
q = s;
while (l > 0) {
if (*p == '.' || *p == '\\') {
/* Dot or backslash */
*(q++) = '\\';
*(q++) = *p;
} else if (*p == '_' ||
*p == '-' ||
(*p >= '0' && *p <= '9') ||
(*p >= 'a' && *p <= 'z') ||
(*p >= 'A' && *p <= 'Z')) {
/* Proper character */
*(q++) = *p;
} else if ((uint8_t) *p >= (uint8_t) ' ' && *p != 127) {
/* Everything else */
*(q++) = '\\';
*(q++) = '0' + (char) ((uint8_t) *p / 100);
*(q++) = '0' + (char) (((uint8_t) *p / 10) % 10);
*(q++) = '0' + (char) ((uint8_t) *p % 10);
} else
return -EINVAL;
p++;
l--;
}
*q = 0;
*ret = s;
r = q - s;
s = NULL;
return r;
}
int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
#ifdef HAVE_LIBIDN
_cleanup_free_ uint32_t *input = NULL;
size_t input_size;
const char *p;
bool contains_8bit = false;
assert(encoded);
assert(decoded);
assert(decoded_max >= DNS_LABEL_MAX);
if (encoded_size <= 0)
return 0;
for (p = encoded; p < encoded + encoded_size; p++)
if ((uint8_t) *p > 127)
contains_8bit = true;
if (!contains_8bit)
return 0;
input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
if (!input)
return -ENOMEM;
if (idna_to_ascii_4i(input, input_size, decoded, 0) != 0)
return -EINVAL;
return strlen(decoded);
#else
return 0;
#endif
}
int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
#ifdef HAVE_LIBIDN
size_t input_size, output_size;
_cleanup_free_ uint32_t *input = NULL;
_cleanup_free_ char *result = NULL;
uint32_t *output = NULL;
size_t w;
/* To be invoked after unescaping */
assert(encoded);
assert(decoded);
if (encoded_size < sizeof(IDNA_ACE_PREFIX)-1)
return 0;
if (memcmp(encoded, IDNA_ACE_PREFIX, sizeof(IDNA_ACE_PREFIX) -1) != 0)
return 0;
input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
if (!input)
return -ENOMEM;
output_size = input_size;
output = newa(uint32_t, output_size);
idna_to_unicode_44i(input, input_size, output, &output_size, 0);
result = stringprep_ucs4_to_utf8(output, output_size, NULL, &w);
if (!result)
return -ENOMEM;
if (w <= 0)
return 0;
if (w+1 > decoded_max)
return -EINVAL;
memcpy(decoded, result, w+1);
return w;
#else
return 0;
#endif
}
int dns_name_normalize(const char *s, char **_ret) {
_cleanup_free_ char *ret = NULL;
size_t n = 0, allocated = 0;
const char *p = s;
bool first = true;
int r;
assert(s);
for (;;) {
_cleanup_free_ char *t = NULL;
char label[DNS_LABEL_MAX];
int k;
r = dns_label_unescape(&p, label, sizeof(label));
if (r < 0)
return r;
if (r == 0) {
if (*p != 0)
return -EINVAL;
break;
}
k = dns_label_undo_idna(label, r, label, sizeof(label));
if (k < 0)
return k;
if (k > 0)
r = k;
r = dns_label_escape(label, r, &t);
if (r < 0)
return r;
if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1))
return -ENOMEM;
if (!first)
ret[n++] = '.';
else
first = false;
memcpy(ret + n, t, r);
n += r;
}
if (n > DNS_NAME_MAX)
return -EINVAL;
if (!GREEDY_REALLOC(ret, allocated, n + 1))
return -ENOMEM;
ret[n] = 0;
if (_ret) {
*_ret = ret;
ret = NULL;
}
return 0;
}
#if 0 /* NM_IGNORED */
unsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_SIZE]) {
const char *p = s;
unsigned long ul = hash_key[0];
int r;
assert(p);
while (*p) {
char label[DNS_LABEL_MAX+1];
int k;
r = dns_label_unescape(&p, label, sizeof(label));
if (r < 0)
break;
k = dns_label_undo_idna(label, r, label, sizeof(label));
if (k < 0)
break;
if (k > 0)
r = k;
label[r] = 0;
ascii_strlower(label);
ul = ul * hash_key[1] + ul + string_hash_func(label, hash_key);
}
return ul;
}
int dns_name_compare_func(const void *a, const void *b) {
const char *x = a, *y = b;
int r, q, k, w;
assert(a);
assert(b);
for (;;) {
char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1];
if (*x == 0 && *y == 0)
return 0;
r = dns_label_unescape(&x, la, sizeof(la));
q = dns_label_unescape(&y, lb, sizeof(lb));
if (r < 0 || q < 0)
return r - q;
k = dns_label_undo_idna(la, r, la, sizeof(la));
w = dns_label_undo_idna(lb, q, lb, sizeof(lb));
if (k < 0 || w < 0)
return k - w;
if (k > 0)
r = k;
if (w > 0)
r = w;
la[r] = lb[q] = 0;
r = strcasecmp(la, lb);
if (r != 0)
return r;
}
}
const struct hash_ops dns_name_hash_ops = {
.hash = dns_name_hash_func,
.compare = dns_name_compare_func
};
int dns_name_equal(const char *x, const char *y) {
int r, q, k, w;
assert(x);
assert(y);
for (;;) {
char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1];
if (*x == 0 && *y == 0)
return true;
r = dns_label_unescape(&x, la, sizeof(la));
if (r < 0)
return r;
k = dns_label_undo_idna(la, r, la, sizeof(la));
if (k < 0)
return k;
if (k > 0)
r = k;
q = dns_label_unescape(&y, lb, sizeof(lb));
if (q < 0)
return q;
w = dns_label_undo_idna(lb, q, lb, sizeof(lb));
if (w < 0)
return w;
if (w > 0)
q = w;
la[r] = lb[q] = 0;
if (strcasecmp(la, lb))
return false;
}
}
int dns_name_endswith(const char *name, const char *suffix) {
const char *n, *s, *saved_n = NULL;
int r, q, k, w;
assert(name);
assert(suffix);
n = name;
s = suffix;
for (;;) {
char ln[DNS_LABEL_MAX+1], ls[DNS_LABEL_MAX+1];
r = dns_label_unescape(&n, ln, sizeof(ln));
if (r < 0)
return r;
k = dns_label_undo_idna(ln, r, ln, sizeof(ln));
if (k < 0)
return k;
if (k > 0)
r = k;
if (!saved_n)
saved_n = n;
q = dns_label_unescape(&s, ls, sizeof(ls));
if (q < 0)
return q;
w = dns_label_undo_idna(ls, q, ls, sizeof(ls));
if (w < 0)
return w;
if (w > 0)
q = w;
if (r == 0 && q == 0)
return true;
if (r == 0 && saved_n == n)
return false;
ln[r] = ls[q] = 0;
if (r != q || strcasecmp(ln, ls)) {
/* Not the same, let's jump back, and try with the next label again */
s = suffix;
n = saved_n;
saved_n = NULL;
}
}
}
int dns_name_reverse(int family, const union in_addr_union *a, char **ret) {
const uint8_t *p;
int r;
assert(a);
assert(ret);
p = (const uint8_t*) a;
if (family == AF_INET)
r = asprintf(ret, "%u.%u.%u.%u.in-addr.arpa", p[3], p[2], p[1], p[0]);
else if (family == AF_INET6)
r = asprintf(ret, "%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.ip6.arpa",
hexchar(p[15] & 0xF), hexchar(p[15] >> 4), hexchar(p[14] & 0xF), hexchar(p[14] >> 4),
hexchar(p[13] & 0xF), hexchar(p[13] >> 4), hexchar(p[12] & 0xF), hexchar(p[12] >> 4),
hexchar(p[11] & 0xF), hexchar(p[11] >> 4), hexchar(p[10] & 0xF), hexchar(p[10] >> 4),
hexchar(p[ 9] & 0xF), hexchar(p[ 9] >> 4), hexchar(p[ 8] & 0xF), hexchar(p[ 8] >> 4),
hexchar(p[ 7] & 0xF), hexchar(p[ 7] >> 4), hexchar(p[ 6] & 0xF), hexchar(p[ 6] >> 4),
hexchar(p[ 5] & 0xF), hexchar(p[ 5] >> 4), hexchar(p[ 4] & 0xF), hexchar(p[ 4] >> 4),
hexchar(p[ 3] & 0xF), hexchar(p[ 3] >> 4), hexchar(p[ 2] & 0xF), hexchar(p[ 2] >> 4),
hexchar(p[ 1] & 0xF), hexchar(p[ 1] >> 4), hexchar(p[ 0] & 0xF), hexchar(p[ 0] >> 4));
else
return -EAFNOSUPPORT;
if (r < 0)
return -ENOMEM;
return 0;
}
int dns_name_address(const char *p, int *family, union in_addr_union *address) {
int r;
assert(p);
assert(family);
assert(address);
r = dns_name_endswith(p, "in-addr.arpa");
if (r < 0)
return r;
if (r > 0) {
uint8_t a[4];
unsigned i;
for (i = 0; i < ELEMENTSOF(a); i++) {
char label[DNS_LABEL_MAX+1];
r = dns_label_unescape(&p, label, sizeof(label));
if (r < 0)
return r;
if (r == 0)
return -EINVAL;
if (r > 3)
return -EINVAL;
r = safe_atou8(label, &a[i]);
if (r < 0)
return r;
}
r = dns_name_equal(p, "in-addr.arpa");
if (r <= 0)
return r;
*family = AF_INET;
address->in.s_addr = htobe32(((uint32_t) a[3] << 24) |
((uint32_t) a[2] << 16) |
((uint32_t) a[1] << 8) |
(uint32_t) a[0]);
return 1;
}
r = dns_name_endswith(p, "ip6.arpa");
if (r < 0)
return r;
if (r > 0) {
struct in6_addr a;
unsigned i;
for (i = 0; i < ELEMENTSOF(a.s6_addr); i++) {
char label[DNS_LABEL_MAX+1];
int x, y;
r = dns_label_unescape(&p, label, sizeof(label));
if (r <= 0)
return r;
if (r != 1)
return -EINVAL;
x = unhexchar(label[0]);
if (x < 0)
return -EINVAL;
r = dns_label_unescape(&p, label, sizeof(label));
if (r <= 0)
return r;
if (r != 1)
return -EINVAL;
y = unhexchar(label[0]);
if (y < 0)
return -EINVAL;
a.s6_addr[ELEMENTSOF(a.s6_addr) - i - 1] = (uint8_t) y << 4 | (uint8_t) x;
}
r = dns_name_equal(p, "ip6.arpa");
if (r <= 0)
return r;
*family = AF_INET6;
address->in6 = a;
return 1;
}
return 0;
}
int dns_name_root(const char *name) {
char label[DNS_LABEL_MAX+1];
int r;
assert(name);
r = dns_label_unescape(&name, label, sizeof(label));
if (r < 0)
return r;
return r == 0 && *name == 0;
}
int dns_name_single_label(const char *name) {
char label[DNS_LABEL_MAX+1];
int r;
assert(name);
r = dns_label_unescape(&name, label, sizeof(label));
if (r < 0)
return r;
if (r == 0)
return 0;
r = dns_label_unescape(&name, label, sizeof(label));
if (r < 0)
return r;
return r == 0 && *name == 0;
}
#endif /* NM_IGNORED */

View file

@ -0,0 +1,65 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2014 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/>.
***/
#pragma once
#include "nm-sd-adapt.h"
#if 0 /* NM_IGNORED */
#include "hashmap.h"
#include "in-addr-util.h"
#endif /* NM_IGNORED */
#define DNS_LABEL_MAX 63
#define DNS_NAME_MAX 255
int dns_label_unescape(const char **name, char *dest, size_t sz);
int dns_label_escape(const char *p, size_t l, char **ret);
int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
int dns_name_normalize(const char *s, char **_ret);
static inline int dns_name_is_valid(const char *s) {
int r;
r = dns_name_normalize(s, NULL);
if (r == -EINVAL)
return 0;
if (r < 0)
return r;
return 1;
}
#if 0 /* NM_IGNORED */
unsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_SIZE]);
int dns_name_compare_func(const void *a, const void *b);
extern const struct hash_ops dns_name_hash_ops;
int dns_name_equal(const char *x, const char *y);
int dns_name_endswith(const char *name, const char *suffix);
int dns_name_reverse(int family, const union in_addr_union *a, char **ret);
int dns_name_address(const char *p, int *family, union in_addr_union *a);
int dns_name_root(const char *name);
int dns_name_single_label(const char *name);
#endif /* NM_IGNORED */