Commit 03b7c384 authored by Thomas Haller's avatar Thomas Haller

systemd: update code from upstream (2017-10-11)

This is a direct dump from systemd git on 2017-10-11, git commit
0da812036f6fd60a7b5477fafb2eead9e98f4c78.

======

SYSTEMD_DIR=../systemd
COMMIT=0da812036f6fd60a7b5477fafb2eead9e98f4c78

(
  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/process-util.h"
nm_copy_sd "src/basic/process-util.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 eba874f8
......@@ -426,7 +426,7 @@ char *octescape(const char *s, size_t len) {
for (f = s, t = r; f < s + len; f++) {
if (*f < ' ' || *f >= 127 || *f == '\\' || *f == '"') {
if (*f < ' ' || *f >= 127 || IN_SET(*f, '\\', '"')) {
*(t++) = '\\';
*(t++) = '0' + (*f >> 6);
*(t++) = '0' + ((*f >> 3) & 8);
......
......@@ -152,7 +152,7 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
for (;; (*p)++, c = **p) {
if (c == 0)
goto finish_force_terminate;
else if ((c == '\'' || c == '"') && (flags & EXTRACT_QUOTES)) {
else if (IN_SET(c, '\'', '"') && (flags & EXTRACT_QUOTES)) {
quote = c;
break;
} else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) {
......
......@@ -30,6 +30,7 @@
#include "alloc-util.h"
#include "ctype.h"
#include "def.h"
#include "env-util.h"
#include "escape.h"
#include "fd-util.h"
......@@ -52,13 +53,17 @@
#define READ_FULL_BYTES_MAX (4U*1024U*1024U)
int write_string_stream_ts(FILE *f, const char *line, bool enforce_newline, struct timespec *ts) {
int write_string_stream_ts(
FILE *f,
const char *line,
WriteStringFileFlags flags,
struct timespec *ts) {
assert(f);
assert(line);
fputs(line, f);
if (enforce_newline && !endswith(line, "\n"))
if (!(flags & WRITE_STRING_FILE_AVOID_NEWLINE) && !endswith(line, "\n"))
fputc('\n', f);
if (ts) {
......@@ -68,10 +73,18 @@ int write_string_stream_ts(FILE *f, const char *line, bool enforce_newline, stru
return -errno;
}
return fflush_and_check(f);
if (flags & WRITE_STRING_FILE_SYNC)
return fflush_sync_and_check(f);
else
return fflush_and_check(f);
}
static int write_string_file_atomic(const char *fn, const char *line, bool enforce_newline, bool do_fsync) {
static int write_string_file_atomic(
const char *fn,
const char *line,
WriteStringFileFlags flags,
struct timespec *ts) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *p = NULL;
int r;
......@@ -85,22 +98,28 @@ static int write_string_file_atomic(const char *fn, const char *line, bool enfor
(void) fchmod_umask(fileno(f), 0644);
r = write_string_stream(f, line, enforce_newline);
if (r >= 0 && do_fsync)
r = fflush_sync_and_check(f);
r = write_string_stream_ts(f, line, flags, ts);
if (r < 0)
goto fail;
if (r >= 0) {
if (rename(p, fn) < 0)
r = -errno;
if (rename(p, fn) < 0) {
r = -errno;
goto fail;
}
if (r < 0)
(void) unlink(p);
return 0;
fail:
(void) unlink(p);
return r;
}
int write_string_file_ts(const char *fn, const char *line, WriteStringFileFlags flags, struct timespec *ts) {
int write_string_file_ts(
const char *fn,
const char *line,
WriteStringFileFlags flags,
struct timespec *ts) {
_cleanup_fclose_ FILE *f = NULL;
int q, r;
......@@ -113,8 +132,7 @@ int write_string_file_ts(const char *fn, const char *line, WriteStringFileFlags
if (flags & WRITE_STRING_FILE_ATOMIC) {
assert(flags & WRITE_STRING_FILE_CREATE);
r = write_string_file_atomic(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE),
flags & WRITE_STRING_FILE_SYNC);
r = write_string_file_atomic(fn, line, flags, ts);
if (r < 0)
goto fail;
......@@ -147,16 +165,10 @@ int write_string_file_ts(const char *fn, const char *line, WriteStringFileFlags
}
}
r = write_string_stream_ts(f, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE), ts);
r = write_string_stream_ts(f, line, flags, ts);
if (r < 0)
goto fail;
if (flags & WRITE_STRING_FILE_SYNC) {
r = fflush_sync_and_check(f);
if (r < 0)
return r;
}
return 0;
fail:
......@@ -177,7 +189,7 @@ fail:
int read_one_line_file(const char *fn, char **line) {
_cleanup_fclose_ FILE *f = NULL;
char t[LINE_MAX], *c;
int r;
assert(fn);
assert(line);
......@@ -186,21 +198,8 @@ int read_one_line_file(const char *fn, char **line) {
if (!f)
return -errno;
if (!fgets(t, sizeof(t), f)) {
if (ferror(f))
return errno > 0 ? -errno : -EIO;
t[0] = 0;
}
c = strdup(t);
if (!c)
return -ENOMEM;
truncate_nl(c);
*line = c;
return 0;
r = read_line(f, LONG_LINE_MAX, line);
return r < 0 ? r : 0;
}
int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
......@@ -259,11 +258,11 @@ int read_full_stream(FILE *f, char **contents, size_t *size) {
if (st.st_size > READ_FULL_BYTES_MAX)
return -E2BIG;
/* Start with the right file size, but be prepared for
* files from /proc which generally report a file size
* of 0 */
/* Start with the right file size, but be prepared for files from /proc which generally report a file
* size of 0. Note that we increase the size to read here by one, so that the first read attempt
* already makes us notice the EOF. */
if (st.st_size > 0)
n = st.st_size;
n = st.st_size + 1;
}
l = 0;
......@@ -276,12 +275,13 @@ int read_full_stream(FILE *f, char **contents, size_t *size) {
return -ENOMEM;
buf = t;
errno = 0;
k = fread(buf + l, 1, n - l, f);
if (k > 0)
l += k;
if (ferror(f))
return -errno;
return errno > 0 ? -errno : -EIO;
if (feof(f))
break;
......@@ -1526,3 +1526,77 @@ int mkdtemp_malloc(const char *template, char **ret) {
*ret = p;
return 0;
}
static inline void funlockfilep(FILE **f) {
funlockfile(*f);
}
int read_line(FILE *f, size_t limit, char **ret) {
_cleanup_free_ char *buffer = NULL;
size_t n = 0, allocated = 0, count = 0;
assert(f);
/* Something like a bounded version of getline().
*
* Considers EOF, \n and \0 end of line delimiters, and does not include these delimiters in the string
* returned.
*
* Returns the number of bytes read from the files (i.e. including delimiters — this hence usually differs from
* the number of characters in the returned string). When EOF is hit, 0 is returned.
*
* The input parameter limit is the maximum numbers of characters in the returned string, i.e. excluding
* delimiters. If the limit is hit we fail and return -ENOBUFS.
*
* If a line shall be skipped ret may be initialized as NULL. */
if (ret) {
if (!GREEDY_REALLOC(buffer, allocated, 1))
return -ENOMEM;
}
{
_cleanup_(funlockfilep) FILE *flocked = f;
flockfile(f);
for (;;) {
int c;
if (n >= limit)
return -ENOBUFS;
errno = 0;
c = fgetc_unlocked(f);
if (c == EOF) {
/* if we read an error, and have no data to return, then propagate the error */
if (ferror_unlocked(f) && n == 0)
return errno > 0 ? -errno : -EIO;
break;
}
count++;
if (IN_SET(c, '\n', 0)) /* Reached a delimiter */
break;
if (ret) {
if (!GREEDY_REALLOC(buffer, allocated, n + 2))
return -ENOMEM;
buffer[n] = (char) c;
}
n++;
}
}
if (ret) {
buffer[n] = 0;
*ret = buffer;
buffer = NULL;
}
return (int) count;
}
......@@ -36,9 +36,9 @@ typedef enum {
WRITE_STRING_FILE_SYNC = 1<<4,
} WriteStringFileFlags;
int write_string_stream_ts(FILE *f, const char *line, bool enforce_newline, struct timespec *ts);
static inline int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
return write_string_stream_ts(f, line, enforce_newline, NULL);
int write_string_stream_ts(FILE *f, const char *line, WriteStringFileFlags flags, struct timespec *ts);
static inline int write_string_stream(FILE *f, const char *line, WriteStringFileFlags flags) {
return write_string_stream_ts(f, line, flags, NULL);
}
int write_string_file_ts(const char *fn, const char *line, WriteStringFileFlags flags, struct timespec *ts);
static inline int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags) {
......@@ -101,3 +101,5 @@ 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);
int read_line(FILE *f, size_t limit, char **ret);
......@@ -324,7 +324,7 @@ int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gi
mkdir_parents(path, 0755);
fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY,
(mode == 0 || mode == MODE_INVALID) ? 0644 : mode);
IN_SET(mode, 0, MODE_INVALID) ? 0644 : mode);
if (fd < 0)
return -errno;
......@@ -359,22 +359,25 @@ int touch(const char *path) {
}
int symlink_idempotent(const char *from, const char *to) {
_cleanup_free_ char *p = NULL;
int r;
assert(from);
assert(to);
if (symlink(from, to) < 0) {
_cleanup_free_ char *p = NULL;
if (errno != EEXIST)
return -errno;
r = readlink_malloc(to, &p);
if (r < 0)
if (r == -EINVAL) /* Not a symlink? In that case return the original error we encountered: -EEXIST */
return -EEXIST;
if (r < 0) /* Any other error? In that case propagate it as is */
return r;
if (!streq(p, from))
return -EINVAL;
if (!streq(p, from)) /* Not the symlink we want it to be? In that case, propagate the original -EEXIST */
return -EEXIST;
}
return 0;
......
......@@ -34,7 +34,7 @@
#include "strv.h"
#include "util.h"
#ifdef ENABLE_DEBUG_HASHMAP
#if ENABLE_DEBUG_HASHMAP
#include <pthread.h>
#include "list.h"
#endif
......@@ -142,7 +142,7 @@ typedef uint8_t dib_raw_t;
#define DIB_FREE UINT_MAX
#ifdef ENABLE_DEBUG_HASHMAP
#if ENABLE_DEBUG_HASHMAP
struct hashmap_debug_info {
LIST_FIELDS(struct hashmap_debug_info, debug_list);
unsigned max_entries; /* high watermark of n_entries */
......@@ -499,7 +499,7 @@ static void base_remove_entry(HashmapBase *h, unsigned idx) {
dibs = dib_raw_ptr(h);
assert(dibs[idx] != DIB_RAW_FREE);
#ifdef ENABLE_DEBUG_HASHMAP
#if ENABLE_DEBUG_HASHMAP
h->debug.rem_count++;
h->debug.last_rem_idx = idx;
#endif
......@@ -508,7 +508,7 @@ static void base_remove_entry(HashmapBase *h, unsigned idx) {
/* Find the stop bucket ("right"). It is either free or has DIB == 0. */
for (right = next_idx(h, left); ; right = next_idx(h, right)) {
raw_dib = dibs[right];
if (raw_dib == 0 || raw_dib == DIB_RAW_FREE)
if (IN_SET(raw_dib, 0, DIB_RAW_FREE))
break;
/* The buckets are not supposed to be all occupied and with DIB > 0.
......@@ -578,7 +578,7 @@ static unsigned hashmap_iterate_in_insertion_order(OrderedHashmap *h, Iterator *
assert(e->p.b.key == i->next_key);
}
#ifdef ENABLE_DEBUG_HASHMAP
#if ENABLE_DEBUG_HASHMAP
i->prev_idx = idx;
#endif
......@@ -635,7 +635,7 @@ static unsigned hashmap_iterate_in_internal_order(HashmapBase *h, Iterator *i) {
}
idx = i->idx;
#ifdef ENABLE_DEBUG_HASHMAP
#if ENABLE_DEBUG_HASHMAP
i->prev_idx = idx;
#endif
......@@ -658,7 +658,7 @@ static unsigned hashmap_iterate_entry(HashmapBase *h, Iterator *i) {
return IDX_NIL;
}
#ifdef ENABLE_DEBUG_HASHMAP
#if ENABLE_DEBUG_HASHMAP
if (i->idx == IDX_FIRST) {
i->put_count = h->debug.put_count;
i->rem_count = h->debug.rem_count;
......@@ -750,7 +750,7 @@ static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enu
shared_hash_key_initialized= true;
}
#ifdef ENABLE_DEBUG_HASHMAP
#if ENABLE_DEBUG_HASHMAP
h->debug.func = func;
h->debug.file = file;
h->debug.line = line;
......@@ -807,7 +807,7 @@ static void hashmap_free_no_clear(HashmapBase *h) {
assert(!h->has_indirect);
assert(!h->n_direct_entries);
#ifdef ENABLE_DEBUG_HASHMAP
#if ENABLE_DEBUG_HASHMAP
assert_se(pthread_mutex_lock(&hashmap_debug_list_mutex) == 0);
LIST_REMOVE(debug_list, hashmap_debug_list, &h->debug);
assert_se(pthread_mutex_unlock(&hashmap_debug_list_mutex) == 0);
......@@ -919,7 +919,7 @@ static bool hashmap_put_robin_hood(HashmapBase *h, unsigned idx,
dib_raw_t raw_dib, *dibs;
unsigned dib, distance;
#ifdef ENABLE_DEBUG_HASHMAP
#if ENABLE_DEBUG_HASHMAP
h->debug.put_count++;
#endif
......@@ -927,7 +927,7 @@ static bool hashmap_put_robin_hood(HashmapBase *h, unsigned idx,
for (distance = 0; ; distance++) {
raw_dib = dibs[idx];
if (raw_dib == DIB_RAW_FREE || raw_dib == DIB_RAW_REHASH) {
if (IN_SET(raw_dib, DIB_RAW_FREE, DIB_RAW_REHASH)) {
if (raw_dib == DIB_RAW_REHASH)
bucket_move_entry(h, swap, idx, IDX_TMP);
......@@ -1012,7 +1012,7 @@ static int hashmap_base_put_boldly(HashmapBase *h, unsigned idx,
assert_se(hashmap_put_robin_hood(h, idx, swap) == false);
n_entries_inc(h);
#ifdef ENABLE_DEBUG_HASHMAP
#if ENABLE_DEBUG_HASHMAP
h->debug.max_entries = MAX(h->debug.max_entries, n_entries(h));
#endif
......@@ -1240,7 +1240,7 @@ int hashmap_replace(Hashmap *h, const void *key, void *value) {
idx = bucket_scan(h, hash, key);
if (idx != IDX_NIL) {
e = plain_bucket_at(h, idx);
#ifdef ENABLE_DEBUG_HASHMAP
#if ENABLE_DEBUG_HASHMAP
/* Although the key is equal, the key pointer may have changed,
* and this would break our assumption for iterating. So count
* this operation as incompatible with iteration. */
......
......@@ -58,7 +58,7 @@ typedef struct Set Set; /* Stores just keys */
typedef struct {
unsigned idx; /* index of an entry to be iterated next */
const void *next_key; /* expected value of that entry's key pointer */
#ifdef ENABLE_DEBUG_HASHMAP
#if ENABLE_DEBUG_HASHMAP
unsigned put_count; /* hashmap's put_count recorded at start of iteration */
unsigned rem_count; /* hashmap's rem_count in previous iteration */
unsigned prev_idx; /* idx in previous iteration */
......@@ -89,7 +89,7 @@ typedef struct {
(Hashmap*)(h), \
(void)0)
#ifdef ENABLE_DEBUG_HASHMAP
#if ENABLE_DEBUG_HASHMAP
# define HASHMAP_DEBUG_PARAMS , const char *func, const char *file, int line
# define HASHMAP_DEBUG_SRC_ARGS , __func__, __FILE__, __LINE__
# define HASHMAP_DEBUG_PASS_ARGS , func, file, line
......
......@@ -90,9 +90,7 @@ static bool hostname_valid_char(char c) {
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9') ||
c == '-' ||
c == '_' ||
c == '.';
IN_SET(c, '-', '_', '.');
}
/**
......@@ -235,7 +233,7 @@ int read_hostname_config(const char *path, char **hostname) {
/* may have comments, ignore them */
FOREACH_LINE(l, f, return -errno) {
truncate_nl(l);
if (l[0] != '\0' && l[0] != '#') {
if (!IN_SET(l[0], '\0', '#')) {
/* found line with value */
name = hostname_cleanup(l);
name = strdup(name);
......
......@@ -308,22 +308,22 @@ int in_addr_from_string(int family, const char *s, union in_addr_union *ret) {
return 0;
}
int in_addr_from_string_auto(const char *s, int *family, union in_addr_union *ret) {
int in_addr_from_string_auto(const char *s, int *ret_family, union in_addr_union *ret) {
int r;
assert(s);
r = in_addr_from_string(AF_INET, s, ret);
if (r >= 0) {
if (family)
*family = AF_INET;
if (ret_family)
*ret_family = AF_INET;
return 0;
}
r = in_addr_from_string(AF_INET6, s, ret);
if (r >= 0) {
if (family)
*family = AF_INET6;
if (ret_family)
*ret_family = AF_INET6;
return 0;
}
......@@ -371,13 +371,13 @@ int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_u
return r;
}
unsigned char in_addr_netmask_to_prefixlen(const struct in_addr *addr) {
unsigned char in4_addr_netmask_to_prefixlen(const struct in_addr *addr) {
assert(addr);
return 32 - u32ctz(be32toh(addr->s_addr));
}
struct in_addr* in_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned char prefixlen) {
struct in_addr* in4_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned char prefixlen) {
assert(addr);
assert(prefixlen <= 32);
......@@ -390,7 +390,7 @@ struct in_addr* in_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned char
return addr;
}
int in_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixlen) {
int in4_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixlen) {
uint8_t msb_octet = *(uint8_t*) addr;
/* addr may not be aligned, so make sure we only access it byte-wise */
......@@ -414,18 +414,18 @@ int in_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixl
return 0;
}
int in_addr_default_subnet_mask(const struct in_addr *addr, struct in_addr *mask) {
int in4_addr_default_subnet_mask(const struct in_addr *addr, struct in_addr *mask) {
unsigned char prefixlen;
int r;
assert(addr);
assert(mask);
r = in_addr_default_prefixlen(addr, &prefixlen);
r = in4_addr_default_prefixlen(addr, &prefixlen);
if (r < 0)
return r;
in_addr_prefixlen_to_netmask(mask, prefixlen);
in4_addr_prefixlen_to_netmask(mask, prefixlen);
return 0;
}
......@@ -435,7 +435,7 @@ int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen)
if (family == AF_INET) {
struct in_addr mask;
if (!in_addr_prefixlen_to_netmask(&mask, prefixlen))
if (!in4_addr_prefixlen_to_netmask(&mask, prefixlen))
return -EINVAL;
addr->in.s_addr &= mask.s_addr;
......@@ -465,10 +465,57 @@ int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen)
return -EAFNOSUPPORT;
}
int in_addr_prefix_from_string(const char *p, int family, union in_addr_union *ret_prefix, uint8_t *ret_prefixlen) {
int in_addr_prefix_covers(int family,
const union in_addr_union *prefix,
unsigned char prefixlen,
const union in_addr_union *address) {
union in_addr_union masked_prefix, masked_address;
int r;
assert(prefix);
assert(address);
masked_prefix = *prefix;
r = in_addr_mask(family, &masked_prefix, prefixlen);
if (r < 0)
return r;
masked_address = *address;
r = in_addr_mask(family, &masked_address, prefixlen);
if (r < 0)
return r;
return in_addr_equal(family, &masked_prefix, &masked_address);
}
int in_addr_parse_prefixlen(int family, const char *p, unsigned char *ret) {
uint8_t u;
int r;
if (!IN_SET(family, AF_INET, AF_INET6))
return -EAFNOSUPPORT;
r = safe_atou8(p, &u);
if (r < 0)
return r;
if (u > FAMILY_ADDRESS_SIZE(family) * 8)
return -ERANGE;
*ret = u;
return 0;
}
int in_addr_prefix_from_string(
const char *p,
int family,
union in_addr_union *ret_prefix,
unsigned char *ret_prefixlen) {
union in_addr_union buffer;
const char *e, *l;
uint8_t k;
unsigned char k;
int r;
assert(p);
......@@ -486,23 +533,58 @@ int in_addr_prefix_from_string(const char *p, int family, union in_addr_union *r