Commit 17820bf4 authored by Thomas Haller's avatar Thomas Haller

systemd: update code from upstream

This is a direct dump from systemd git on 2017-01-04, git commit
6a47fd894d601f7e8e88dec4cb35dfb7d7c15eff.

======

SYSTEMD_DIR=../systemd
COMMIT=6a47fd894d601f7e8e88dec4cb35dfb7d7c15eff

(
  cd "$SYSTEMD_DIR"
  git checkout "$COMMIT"
  git reset --hard
  git clean -fdx
)

git ls-files :/src/systemd/src/ | xargs -d '\n' rm -f

nm_copy_sd() {
    mkdir -p "./src/systemd/$(dirname "$1")"
    cp "$SYSTEMD_DIR/$1" "./src/systemd/$1"
}

nm_copy_sd "src/basic/alloc-util.c"
nm_copy_sd "src/basic/alloc-util.h"
nm_copy_sd "src/basic/async.h"
nm_copy_sd "src/basic/escape.c"
nm_copy_sd "src/basic/escape.h"
nm_copy_sd "src/basic/ether-addr-util.c"
nm_copy_sd "src/basic/ether-addr-util.h"
nm_copy_sd "src/basic/extract-word.c"
nm_copy_sd "src/basic/extract-word.h"
nm_copy_sd "src/basic/fileio.c"
nm_copy_sd "src/basic/fileio.h"
nm_copy_sd "src/basic/fd-util.c"
nm_copy_sd "src/basic/fd-util.h"
nm_copy_sd "src/basic/fs-util.c"
nm_copy_sd "src/basic/fs-util.h"
nm_copy_sd "src/basic/hash-funcs.c"
nm_copy_sd "src/basic/hash-funcs.h"
nm_copy_sd "src/basic/hashmap.c"
nm_copy_sd "src/basic/hashmap.h"
nm_copy_sd "src/basic/hexdecoct.c"
nm_copy_sd "src/basic/hexdecoct.h"
nm_copy_sd "src/basic/hostname-util.c"
nm_copy_sd "src/basic/hostname-util.h"
nm_copy_sd "src/basic/in-addr-util.c"
nm_copy_sd "src/basic/in-addr-util.h"
nm_copy_sd "src/basic/io-util.c"
nm_copy_sd "src/basic/io-util.h"
nm_copy_sd "src/basic/list.h"
nm_copy_sd "src/basic/log.h"
nm_copy_sd "src/basic/macro.h"
nm_copy_sd "src/basic/mempool.h"
nm_copy_sd "src/basic/mempool.c"
nm_copy_sd "src/basic/parse-util.c"
nm_copy_sd "src/basic/parse-util.h"
nm_copy_sd "src/basic/path-util.c"
nm_copy_sd "src/basic/path-util.h"
nm_copy_sd "src/basic/prioq.h"
nm_copy_sd "src/basic/prioq.c"
nm_copy_sd "src/basic/random-util.c"
nm_copy_sd "src/basic/random-util.h"
nm_copy_sd "src/basic/refcnt.h"
nm_copy_sd "src/basic/set.h"
nm_copy_sd "src/basic/signal-util.h"
nm_copy_sd "src/basic/siphash24.c"
nm_copy_sd "src/basic/siphash24.h"
nm_copy_sd "src/basic/socket-util.c"
nm_copy_sd "src/basic/socket-util.h"
nm_copy_sd "src/basic/sparse-endian.h"
nm_copy_sd "src/basic/stdio-util.h"
nm_copy_sd "src/basic/string-table.c"
nm_copy_sd "src/basic/string-table.h"
nm_copy_sd "src/basic/string-util.c"
nm_copy_sd "src/basic/string-util.h"
nm_copy_sd "src/basic/strv.c"
nm_copy_sd "src/basic/strv.h"
nm_copy_sd "src/basic/time-util.c"
nm_copy_sd "src/basic/time-util.h"
nm_copy_sd "src/basic/umask-util.h"
nm_copy_sd "src/basic/unaligned.h"
nm_copy_sd "src/basic/utf8.c"
nm_copy_sd "src/basic/utf8.h"
nm_copy_sd "src/basic/util.c"
nm_copy_sd "src/basic/util.h"
nm_copy_sd "src/libsystemd-network/arp-util.c"
nm_copy_sd "src/libsystemd-network/arp-util.h"
nm_copy_sd "src/libsystemd-network/dhcp6-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp6-lease-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp6-network.c"
nm_copy_sd "src/libsystemd-network/dhcp6-option.c"
nm_copy_sd "src/libsystemd-network/dhcp6-protocol.h"
nm_copy_sd "src/libsystemd-network/dhcp-identifier.c"
nm_copy_sd "src/libsystemd-network/dhcp-identifier.h"
nm_copy_sd "src/libsystemd-network/dhcp-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp-lease-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp-network.c"
nm_copy_sd "src/libsystemd-network/dhcp-option.c"
nm_copy_sd "src/libsystemd-network/dhcp-packet.c"
nm_copy_sd "src/libsystemd-network/dhcp-protocol.h"
nm_copy_sd "src/libsystemd-network/lldp-internal.h"
nm_copy_sd "src/libsystemd-network/lldp-neighbor.c"
nm_copy_sd "src/libsystemd-network/lldp-neighbor.h"
nm_copy_sd "src/libsystemd-network/lldp-network.c"
nm_copy_sd "src/libsystemd-network/lldp-network.h"
nm_copy_sd "src/libsystemd-network/network-internal.c"
nm_copy_sd "src/libsystemd-network/network-internal.h"
nm_copy_sd "src/libsystemd-network/sd-dhcp6-client.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp6-lease.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp-client.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp-lease.c"
nm_copy_sd "src/libsystemd-network/sd-ipv4ll.c"
nm_copy_sd "src/libsystemd-network/sd-ipv4acd.c"
nm_copy_sd "src/libsystemd-network/sd-lldp.c"
nm_copy_sd "src/libsystemd/sd-event/sd-event.c"
nm_copy_sd "src/libsystemd/sd-id128/id128-util.c"
nm_copy_sd "src/libsystemd/sd-id128/id128-util.h"
nm_copy_sd "src/libsystemd/sd-id128/sd-id128.c"
nm_copy_sd "src/shared/dns-domain.c"
nm_copy_sd "src/shared/dns-domain.h"
nm_copy_sd "src/systemd/_sd-common.h"
nm_copy_sd "src/systemd/sd-dhcp6-client.h"
nm_copy_sd "src/systemd/sd-dhcp6-lease.h"
nm_copy_sd "src/systemd/sd-dhcp-client.h"
nm_copy_sd "src/systemd/sd-dhcp-lease.h"
nm_copy_sd "src/systemd/sd-event.h"
nm_copy_sd "src/systemd/sd-ndisc.h"
nm_copy_sd "src/systemd/sd-id128.h"
nm_copy_sd "src/systemd/sd-ipv4acd.h"
nm_copy_sd "src/systemd/sd-ipv4ll.h"
nm_copy_sd "src/systemd/sd-lldp.h"
parent e68056a2
......@@ -227,8 +227,8 @@ int extract_first_word_and_warn(
*p = save;
r = extract_first_word(p, ret, separators, flags|EXTRACT_CUNESCAPE_RELAX);
if (r >= 0) {
/* It worked this time, hence it must have been an invalid escape sequence we could correct. */
log_syntax(unit, LOG_WARNING, filename, line, EINVAL, "Invalid escape sequences in line, correcting: \"%s\"", rvalue);
/* It worked this time, hence it must have been an invalid escape sequence. */
log_syntax(unit, LOG_WARNING, filename, line, EINVAL, "Ignoring unknown escape sequences: \"%s\"", *ret);
return r;
}
......
......@@ -24,6 +24,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include "dirent-util.h"
#include "fd-util.h"
#include "fs-util.h"
#include "macro.h"
......@@ -234,12 +235,9 @@ int close_all_fds(const int except[], unsigned n_except) {
return r;
}
while ((de = readdir(d))) {
FOREACH_DIRENT(de, d, return -errno) {
int fd = -1;
if (hidden_or_backup_file(de->d_name))
continue;
if (safe_atoi(de->d_name, &fd) < 0)
/* Let's better ignore this, just in case */
continue;
......
......@@ -1409,3 +1409,22 @@ int read_nul_string(FILE *f, char **ret) {
return 0;
}
int mkdtemp_malloc(const char *template, char **ret) {
char *p;
assert(template);
assert(ret);
p = strdup(template);
if (!p)
return -ENOMEM;
if (!mkdtemp(p)) {
free(p);
return -errno;
}
*ret = p;
return 0;
}
......@@ -88,3 +88,5 @@ int open_tmpfile_linkable(const char *target, int flags, char **ret_path);
int link_tmpfile(int fd, const char *path, const char *target);
int read_nul_string(FILE *f, char **ret);
int mkdtemp_malloc(const char *template, char **ret);
......@@ -17,7 +17,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <dirent.h>
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
......@@ -224,25 +223,25 @@ int readlink_and_make_absolute(const char *p, char **r) {
return 0;
}
int readlink_and_canonicalize(const char *p, char **r) {
int readlink_and_canonicalize(const char *p, const char *root, char **ret) {
char *t, *s;
int j;
int r;
assert(p);
assert(r);
assert(ret);
j = readlink_and_make_absolute(p, &t);
if (j < 0)
return j;
r = readlink_and_make_absolute(p, &t);
if (r < 0)
return r;
s = canonicalize_file_name(t);
if (s) {
r = chase_symlinks(t, root, 0, &s);
if (r < 0)
/* If we can't follow up, then let's return the original string, slightly cleaned up. */
*ret = path_kill_slashes(t);
else {
*ret = s;
free(t);
*r = s;
} else
*r = t;
path_kill_slashes(*r);
}
return 0;
}
......@@ -446,6 +445,7 @@ int mkfifo_atomic(const char *path, mode_t mode) {
int get_files_in_directory(const char *path, char ***list) {
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
size_t bufsize = 0, n = 0;
_cleanup_strv_free_ char **l = NULL;
......@@ -459,16 +459,7 @@ int get_files_in_directory(const char *path, char ***list) {
if (!d)
return -errno;
for (;;) {
struct dirent *de;
errno = 0;
de = readdir(d);
if (!de && errno > 0)
return -errno;
if (!de)
break;
FOREACH_DIRENT_ALL(de, d, return -errno) {
dirent_ensure_type(d, de);
if (!dirent_is_file(de))
......@@ -598,10 +589,11 @@ int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
return r;
}
int chase_symlinks(const char *path, const char *_root, char **ret) {
int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret) {
_cleanup_free_ char *buffer = NULL, *done = NULL, *root = NULL;
_cleanup_close_ int fd = -1;
unsigned max_follow = 32; /* how many symlinks to follow before giving up and returning ELOOP */
bool exists = true;
char *todo;
int r;
......@@ -610,26 +602,39 @@ int chase_symlinks(const char *path, const char *_root, char **ret) {
/* This is a lot like canonicalize_file_name(), but takes an additional "root" parameter, that allows following
* symlinks relative to a root directory, instead of the root of the host.
*
* Note that "root" matters only if we encounter an absolute symlink, it's unused otherwise. Most importantly
* this means the path parameter passed in is not prefixed by it.
* Note that "root" primarily matters if we encounter an absolute symlink. It is also used when following
* relative symlinks to ensure they cannot be used to "escape" the root directory. The path parameter passed is
* assumed to be already prefixed by it, except if the CHASE_PREFIX_ROOT flag is set, in which case it is first
* prefixed accordingly.
*
* Algorithmically this operates on two path buffers: "done" are the components of the path we already
* processed and resolved symlinks, "." and ".." of. "todo" are the components of the path we still need to
* process. On each iteration, we move one component from "todo" to "done", processing it's special meaning
* each time. The "todo" path always starts with at least one slash, the "done" path always ends in no
* slash. We always keep an O_PATH fd to the component we are currently processing, thus keeping lookup races
* at a minimum. */
r = path_make_absolute_cwd(path, &buffer);
if (r < 0)
return r;
* at a minimum.
*
* Suggested usage: whenever you want to canonicalize a path, use this function. Pass the absolute path you got
* as-is: fully qualified and relative to your host's root. Optionally, specify the root parameter to tell this
* function what to do when encountering a symlink with an absolute path as directory: prefix it by the
* specified path.
*
* Note: there's also chase_symlinks_prefix() (see below), which as first step prefixes the passed path by the
* passed root. */
if (_root) {
r = path_make_absolute_cwd(_root, &root);
if (original_root) {
r = path_make_absolute_cwd(original_root, &root);
if (r < 0)
return r;
if (flags & CHASE_PREFIX_ROOT)
path = prefix_roota(root, path);
}
r = path_make_absolute_cwd(path, &buffer);
if (r < 0)
return r;
fd = open("/", O_CLOEXEC|O_NOFOLLOW|O_PATH);
if (fd < 0)
return -errno;
......@@ -665,18 +670,20 @@ int chase_symlinks(const char *path, const char *_root, char **ret) {
_cleanup_free_ char *parent = NULL;
int fd_parent = -1;
/* If we already are at the top, then going up will not change anything. This is in-line with
* how the kernel handles this. */
if (isempty(done) || path_equal(done, "/"))
return -EINVAL;
continue;
parent = dirname_malloc(done);
if (!parent)
return -ENOMEM;
/* Don't allow this to leave the root dir */
/* Don't allow this to leave the root dir. */
if (root &&
path_startswith(done, root) &&
!path_startswith(parent, root))
return -EINVAL;
continue;
free_and_replace(done, parent);
......@@ -692,8 +699,25 @@ int chase_symlinks(const char *path, const char *_root, char **ret) {
/* Otherwise let's see what this is. */
child = openat(fd, first + n, O_CLOEXEC|O_NOFOLLOW|O_PATH);
if (child < 0)
if (child < 0) {
if (errno == ENOENT &&
(flags & CHASE_NONEXISTENT) &&
(isempty(todo) || path_is_safe(todo))) {
/* If CHASE_NONEXISTENT is set, and the path does not exist, then that's OK, return
* what we got so far. But don't allow this if the remaining path contains "../ or "./"
* or something else weird. */
if (!strextend(&done, first, todo, NULL))
return -ENOMEM;
exists = false;
break;
}
return -errno;
}
if (fstat(child, &st) < 0)
return -errno;
......@@ -778,5 +802,5 @@ int chase_symlinks(const char *path, const char *_root, char **ret) {
*ret = done;
done = NULL;
return 0;
return exists;
}
......@@ -39,7 +39,7 @@ 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 readlink_and_canonicalize(const char *p, const char *root, char **r);
int readlink_and_make_absolute_root(const char *root, const char *path, char **ret);
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
......@@ -78,4 +78,16 @@ union inotify_event_buffer {
int inotify_add_watch_fd(int fd, int what, uint32_t mask);
int chase_symlinks(const char *path, const char *_root, char **ret);
enum {
CHASE_PREFIX_ROOT = 1, /* If set, the specified path will be prefixed by the specified root before beginning the iteration */
CHASE_NONEXISTENT = 2, /* If set, it's OK if the path doesn't actually exist. */
};
int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flags, char **ret);
/* Useful for usage with _cleanup_(), removes a directory and frees the pointer */
static inline void rmdir_and_free(char *p) {
(void) rmdir(p);
free(p);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, rmdir_and_free);
......@@ -31,15 +31,9 @@
#include "util.h"
bool in4_addr_is_null(const struct in_addr *a) {
return a->s_addr == 0;
}
assert(a);
bool in6_addr_is_null(const struct in6_addr *a) {
return
a->s6_addr32[0] == 0 &&
a->s6_addr32[1] == 0 &&
a->s6_addr32[2] == 0 &&
a->s6_addr32[3] == 0;
return a->s_addr == 0;
}
int in_addr_is_null(int family, const union in_addr_union *u) {
......@@ -49,16 +43,22 @@ int in_addr_is_null(int family, const union in_addr_union *u) {
return in4_addr_is_null(&u->in);
if (family == AF_INET6)
return in6_addr_is_null(&u->in6);
return IN6_IS_ADDR_UNSPECIFIED(&u->in6);
return -EAFNOSUPPORT;
}
bool in4_addr_is_link_local(const struct in_addr *a) {
assert(a);
return (be32toh(a->s_addr) & UINT32_C(0xFFFF0000)) == (UINT32_C(169) << 24 | UINT32_C(254) << 16);
}
int in_addr_is_link_local(int family, const union in_addr_union *u) {
assert(u);
if (family == AF_INET)
return (be32toh(u->in.s_addr) & UINT32_C(0xFFFF0000)) == (UINT32_C(169) << 24 | UINT32_C(254) << 16);
return in4_addr_is_link_local(&u->in);
if (family == AF_INET6)
return IN6_IS_ADDR_LINKLOCAL(&u->in6);
......@@ -66,12 +66,18 @@ int in_addr_is_link_local(int family, const union in_addr_union *u) {
return -EAFNOSUPPORT;
}
bool in4_addr_is_localhost(const struct in_addr *a) {
assert(a);
/* All of 127.x.x.x is localhost. */
return (be32toh(a->s_addr) & UINT32_C(0xFF000000)) == UINT32_C(127) << 24;
}
int in_addr_is_localhost(int family, const union in_addr_union *u) {
assert(u);
if (family == AF_INET)
/* All of 127.x.x.x is localhost. */
return (be32toh(u->in.s_addr) & UINT32_C(0xFF000000)) == UINT32_C(127) << 24;
return in4_addr_is_localhost(&u->in);
if (family == AF_INET6)
return IN6_IS_ADDR_LOOPBACK(&u->in6);
......@@ -277,15 +283,14 @@ fallback:
}
int in_addr_from_string(int family, const char *s, union in_addr_union *ret) {
union in_addr_union buffer;
assert(s);
assert(ret);
if (!IN_SET(family, AF_INET, AF_INET6))
return -EAFNOSUPPORT;
errno = 0;
if (inet_pton(family, s, ret) <= 0)
if (inet_pton(family, s, ret ?: &buffer) <= 0)
return errno > 0 ? -errno : -EINVAL;
return 0;
......@@ -295,18 +300,18 @@ int in_addr_from_string_auto(const char *s, int *family, union in_addr_union *re
int r;
assert(s);
assert(family);
assert(ret);
r = in_addr_from_string(AF_INET, s, ret);
if (r >= 0) {
*family = AF_INET;
if (family)
*family = AF_INET;
return 0;
}
r = in_addr_from_string(AF_INET6, s, ret);
if (r >= 0) {
*family = AF_INET6;
if (family)
*family = AF_INET6;
return 0;
}
......
......@@ -37,11 +37,14 @@ struct in_addr_data {
};
bool in4_addr_is_null(const struct in_addr *a);
bool in6_addr_is_null(const struct in6_addr *a);
int in_addr_is_null(int family, const union in_addr_union *u);
bool in4_addr_is_link_local(const struct in_addr *a);
int in_addr_is_link_local(int family, const union in_addr_union *u);
bool in4_addr_is_localhost(const struct in_addr *a);
int in_addr_is_localhost(int family, const union in_addr_union *u);
int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b);
int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen);
int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen);
......
......@@ -574,3 +574,19 @@ int parse_nice(const char *p, int *ret) {
*ret = n;
return 0;
}
int parse_ip_port(const char *s, uint16_t *ret) {
uint16_t l;
int r;
r = safe_atou16(s, &l);
if (r < 0)
return r;
if (l == 0)
return -EINVAL;
*ret = (uint16_t) l;
return 0;
}
......@@ -110,3 +110,5 @@ int parse_percent_unbounded(const char *p);
int parse_percent(const char *p);
int parse_nice(const char *p, int *ret);
int parse_ip_port(const char *s, uint16_t *ret);
......@@ -220,10 +220,11 @@ int path_strv_make_absolute_cwd(char **l) {
return 0;
}
char **path_strv_resolve(char **l, const char *prefix) {
char **path_strv_resolve(char **l, const char *root) {
char **s;
unsigned k = 0;
bool enomem = false;
int r;
if (strv_isempty(l))
return l;
......@@ -233,17 +234,17 @@ char **path_strv_resolve(char **l, const char *prefix) {
* changes on failure. */
STRV_FOREACH(s, l) {
char *t, *u;
_cleanup_free_ char *orig = NULL;
char *t, *u;
if (!path_is_absolute(*s)) {
free(*s);
continue;
}
if (prefix) {
if (root) {
orig = *s;
t = strappend(prefix, orig);
t = prefix_root(root, orig);
if (!t) {
enomem = true;
continue;
......@@ -251,28 +252,26 @@ char **path_strv_resolve(char **l, const char *prefix) {
} else
t = *s;
errno = 0;
u = canonicalize_file_name(t);
if (!u) {
if (errno == ENOENT) {
if (prefix) {
u = orig;
orig = NULL;
free(t);
} else
u = t;
} else {
r = chase_symlinks(t, root, 0, &u);
if (r == -ENOENT) {
if (root) {
u = orig;
orig = NULL;
free(t);
if (errno == ENOMEM || errno == 0)
enomem = true;
} else
u = t;
} else if (r < 0) {
free(t);
continue;
}
} else if (prefix) {
if (r == -ENOMEM)
enomem = true;
continue;
} else if (root) {
char *x;
free(t);
x = path_startswith(u, prefix);
x = path_startswith(u, root);
if (x) {
/* restore the slash if it was lost */
if (!startswith(x, "/"))
......@@ -304,12 +303,12 @@ char **path_strv_resolve(char **l, const char *prefix) {
return l;
}
char **path_strv_resolve_uniq(char **l, const char *prefix) {
char **path_strv_resolve_uniq(char **l, const char *root) {
if (strv_isempty(l))
return l;
if (!path_strv_resolve(l, prefix))
if (!path_strv_resolve(l, root))
return NULL;
return strv_uniq(l);
......
......@@ -24,6 +24,7 @@
#include <stddef.h>
#include "macro.h"
#include "string-util.h"
#include "time-util.h"
#define DEFAULT_PATH_NORMAL "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"
......@@ -65,9 +66,21 @@ static inline bool path_equal_ptr(const char *a, const char *b) {
_found; \
})
#define PATH_STARTSWITH_SET(p, ...) \
({ \
char **s; \
bool _found = false; \
STRV_FOREACH(s, STRV_MAKE(__VA_ARGS__)) \
if (path_startswith(p, *s)) { \
_found = true; \
break; \
} \
_found; \
})
int 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);
char** path_strv_resolve(char **l, const char *root);
char** path_strv_resolve_uniq(char **l, const char *root);
int find_binary(const char *name, char **filename);
......
......@@ -883,6 +883,7 @@ static char* extract_multiplier(char *p, usec_t *multiplier) {
{ "y", USEC_PER_YEAR },
{ "usec", 1ULL },
{ "us", 1ULL },
{ "µs", 1ULL },
};
unsigned i;
......@@ -1016,6 +1017,7 @@ int parse_nsec(const char *t, nsec_t *nsec) {
{ "y", NSEC_PER_YEAR },
{ "usec", NSEC_PER_USEC },
{ "us", NSEC_PER_USEC },
{ "µs", NSEC_PER_USEC },
{ "nsec", 1ULL },
{ "ns", 1ULL },
{ "", 1ULL }, /* default is nsec */
......
......@@ -18,7 +18,6 @@
***/
#include <alloca.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <sched.h>
......@@ -493,7 +492,7 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
u = nmemb;
while (l < u) {
idx = (l + u) / 2;
p = (void *)(((const char *) base) + (idx * size));
p = (const char *) base + idx * size;
comparison = compar(key, p, arg);
if (comparison < 0)
u = idx;
......@@ -508,28 +507,17 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
int on_ac_power(void) {
bool found_offline = false, found_online = false;
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
d = opendir("/sys/class/power_supply");
if (!d)
return errno == ENOENT ? true : -errno;
for (;;) {
struct dirent *de;
FOREACH_DIRENT(de, d, return -errno) {
_cleanup_close_ int fd = -1, device = -1;
char contents[6];
ssize_t n;
errno = 0;
de = readdir(d);
if (!de && errno > 0)
return -errno;
if (!de)
break;
if (hidden_or_backup_file(de->d_name))
continue;
device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (device < 0) {
if (errno == ENOENT || errno == ENOTDIR)
......
......@@ -30,11 +30,11 @@
#include "dhcp-protocol.h"
#include "socket-util.h"
int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link,
int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link,
uint32_t xid, const uint8_t *mac_addr,
size_t mac_addr_len, uint16_t arp_type,
uint16_t port);
int dhcp_network_bind_udp_socket(be32_t address, uint16_t port);
int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port);
int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
const void *packet, size_t len);
int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port,
......
......@@ -19,6 +19,7 @@
#include <errno.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <stdio.h>
#include <string.h>
......@@ -156,13 +157,14 @@ int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link,
bcast_addr, &eth_mac, arp_type, dhcp_hlen, port);
}
int dhcp_network_bind_udp_socket(be32_t address, uint16_t port) {
int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port) {
union sockaddr_union src = {
.in.sin_family = AF_INET,
.in.sin_port = htobe16(port),
.in.sin_addr.s_addr = address,
};
_cleanup_close_ int s = -1;
char ifname[IF_NAMESIZE] = "";
int r, on = 1, tos = IPTOS_CLASS_CS6;
s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
......@@ -177,6 +179,15 @@ int dhcp_network_bind_udp_socket(be32_t address, uint16_t port) {
if (r < 0)
return -errno;
if (ifindex > 0) {
if (if_indextoname(ifindex, ifname) == 0)
return -errno;
r = setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname));
if (r < 0)
return -errno;
}
if (address == INADDR_ANY) {
r = setsockopt(s, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on));
if (r < 0)
......@@ -185,6 +196,7 @@ int dhcp_network_bind_udp_socket(be32_t address, uint16_t port) {
r = setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
if (r < 0)
return -errno;
} else {
r = setsockopt(s, IPPROTO_IP, IP_FREEBIND, &on, sizeof(on));
if (r < 0)
......
......@@ -86,6 +86,28 @@ int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result
return 0;
}
static bool net_condition_test_strv(char * const *raw_patterns,
const char *string) {
if (strv_isempty(raw_patterns))
return true;
/* If the patterns begin with "!", edit it out and negate the test. */
if (raw_patterns[0][0] == '!') {
char **patterns;
unsigned i, length;
length = strv_length(raw_patterns) + 1; /* Include the NULL. */