mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-09 15:50:26 +01:00
systemd: merge branch 'systemd'
This commit is contained in:
commit
2deaa39921
39 changed files with 1888 additions and 2775 deletions
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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; \
|
||||
})
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
197
src/systemd/src/basic/hostname-util.c
Normal file
197
src/systemd/src/basic/hostname-util.c
Normal 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 */
|
||||
41
src/systemd/src/basic/hostname-util.h
Normal file
41
src/systemd/src/basic/hostname-util.h
Normal 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);
|
||||
|
|
@ -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); \
|
||||
})
|
||||
|
|
@ -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"
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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; \
|
||||
})
|
||||
137
src/systemd/src/basic/random-util.c
Normal file
137
src/systemd/src/basic/random-util.c
Normal 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();
|
||||
}
|
||||
40
src/systemd/src/basic/random-util.h
Normal file
40
src/systemd/src/basic/random-util.h
Normal 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;
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
@ -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) {
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
|
@ -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);
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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))) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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]) {
|
||||
|
|
|
|||
617
src/systemd/src/shared/dns-domain.c
Normal file
617
src/systemd/src/shared/dns-domain.c
Normal 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 */
|
||||
65
src/systemd/src/shared/dns-domain.h
Normal file
65
src/systemd/src/shared/dns-domain.h
Normal 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 */
|
||||
Loading…
Add table
Reference in a new issue