summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-09-21 10:38:52 +0200
committerThomas Haller <thaller@redhat.com>2017-09-21 15:08:50 +0200
commiteba874f859945a7a9aa22735cd20b144dc0eb918 (patch)
tree8bffe675876603a5f189f7d21a1c176cc59f09c8
parent770ad94cba6aa925f263cf75715d42ef424da68e (diff)
downloadNetworkManager-eba874f859945a7a9aa22735cd20b144dc0eb918.tar.gz
systemd: update code from upstream (2017-09-21)
This is a direct dump from systemd git on 2017-09-21, git commit f679ed61163468f4fb2d4a17fa0984c8c1f0ba36. ====== SYSTEMD_DIR=../systemd COMMIT=f679ed61163468f4fb2d4a17fa0984c8c1f0ba36 ( 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"
-rw-r--r--src/systemd/src/basic/fs-util.c4
-rw-r--r--src/systemd/src/basic/fs-util.h1
-rw-r--r--src/systemd/src/basic/process-util.c26
-rw-r--r--src/systemd/src/basic/process-util.h1
-rw-r--r--src/systemd/src/basic/time-util.c182
-rw-r--r--src/systemd/src/basic/util.c131
-rw-r--r--src/systemd/src/basic/util.h3
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-client.c82
-rw-r--r--src/systemd/src/systemd/sd-dhcp-client.h16
9 files changed, 369 insertions, 77 deletions
diff --git a/src/systemd/src/basic/fs-util.c b/src/systemd/src/basic/fs-util.c
index 5e1163c6a7..fdedeffb9a 100644
--- a/src/systemd/src/basic/fs-util.c
+++ b/src/systemd/src/basic/fs-util.c
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
+#include <linux/magic.h>
#include <time.h>
#include <unistd.h>
@@ -721,6 +722,9 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
if (fstat(child, &st) < 0)
return -errno;
+ if ((flags & CHASE_NO_AUTOFS) &&
+ fd_check_fstype(child, AUTOFS_SUPER_MAGIC) > 0)
+ return -EREMOTE;
if (S_ISLNK(st.st_mode)) {
char *joined;
diff --git a/src/systemd/src/basic/fs-util.h b/src/systemd/src/basic/fs-util.h
index 094acf1799..d3342d5cda 100644
--- a/src/systemd/src/basic/fs-util.h
+++ b/src/systemd/src/basic/fs-util.h
@@ -81,6 +81,7 @@ int inotify_add_watch_fd(int fd, int what, uint32_t mask);
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. */
+ CHASE_NO_AUTOFS = 4, /* If set, return -EREMOTE if autofs mount point found */
};
int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flags, char **ret);
diff --git a/src/systemd/src/basic/process-util.c b/src/systemd/src/basic/process-util.c
index e4cde6561b..9d0154117b 100644
--- a/src/systemd/src/basic/process-util.c
+++ b/src/systemd/src/basic/process-util.c
@@ -904,6 +904,28 @@ const char* personality_to_string(unsigned long p) {
return architecture_to_string(architecture);
}
+int safe_personality(unsigned long p) {
+ int ret;
+
+ /* So here's the deal, personality() is weirdly defined by glibc. In some cases it returns a failure via errno,
+ * and in others as negative return value containing an errno-like value. Let's work around this: this is a
+ * wrapper that uses errno if it is set, and uses the return value otherwise. And then it sets both errno and
+ * the return value indicating the same issue, so that we are definitely on the safe side.
+ *
+ * See https://github.com/systemd/systemd/issues/6737 */
+
+ errno = 0;
+ ret = personality(p);
+ if (ret < 0) {
+ if (errno != 0)
+ return -errno;
+
+ errno = -ret;
+ }
+
+ return ret;
+}
+
int opinionated_personality(unsigned long *ret) {
int current;
@@ -911,9 +933,9 @@ int opinionated_personality(unsigned long *ret) {
* opinionated though, and ignores all the finer-grained bits and exotic personalities, only distinguishing the
* two most relevant personalities: PER_LINUX and PER_LINUX32. */
- current = personality(PERSONALITY_INVALID);
+ current = safe_personality(PERSONALITY_INVALID);
if (current < 0)
- return -errno;
+ return current;
if (((unsigned long) current & 0xffff) == PER_LINUX32)
*ret = PER_LINUX32;
diff --git a/src/systemd/src/basic/process-util.h b/src/systemd/src/basic/process-util.h
index d71db2df7e..82af2f9181 100644
--- a/src/systemd/src/basic/process-util.h
+++ b/src/systemd/src/basic/process-util.h
@@ -91,6 +91,7 @@ bool oom_score_adjust_is_valid(int oa);
unsigned long personality_from_string(const char *p);
const char *personality_to_string(unsigned long);
+int safe_personality(unsigned long p);
int opinionated_personality(unsigned long *ret);
int ioprio_class_to_string_alloc(int i, char **s);
diff --git a/src/systemd/src/basic/time-util.c b/src/systemd/src/basic/time-util.c
index 68ba86f6a5..00979bfe59 100644
--- a/src/systemd/src/basic/time-util.c
+++ b/src/systemd/src/basic/time-util.c
@@ -21,6 +21,7 @@
#include <limits.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/timerfd.h>
@@ -596,7 +597,7 @@ int timestamp_deserialize(const char *value, usec_t *timestamp) {
return r;
}
-int parse_timestamp(const char *t, usec_t *usec) {
+static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
static const struct {
const char *name;
const int nr;
@@ -617,7 +618,7 @@ int parse_timestamp(const char *t, usec_t *usec) {
{ "Sat", 6 },
};
- const char *k, *utc, *tzn = NULL;
+ const char *k, *utc = NULL, *tzn = NULL;
struct tm tm, copy;
time_t x;
usec_t x_usec, plus = 0, minus = 0, ret;
@@ -645,84 +646,86 @@ int parse_timestamp(const char *t, usec_t *usec) {
assert(t);
assert(usec);
- if (t[0] == '@')
+ if (t[0] == '@' && !with_tz)
return parse_sec(t + 1, usec);
ret = now(CLOCK_REALTIME);
- if (streq(t, "now"))
- goto finish;
+ if (!with_tz) {
+ if (streq(t, "now"))
+ goto finish;
- else if (t[0] == '+') {
- r = parse_sec(t+1, &plus);
- if (r < 0)
- return r;
+ else if (t[0] == '+') {
+ r = parse_sec(t+1, &plus);
+ if (r < 0)
+ return r;
- goto finish;
+ goto finish;
- } else if (t[0] == '-') {
- r = parse_sec(t+1, &minus);
- if (r < 0)
- return r;
+ } else if (t[0] == '-') {
+ r = parse_sec(t+1, &minus);
+ if (r < 0)
+ return r;
- goto finish;
+ goto finish;
- } else if ((k = endswith(t, " ago"))) {
- t = strndupa(t, k - t);
+ } else if ((k = endswith(t, " ago"))) {
+ t = strndupa(t, k - t);
- r = parse_sec(t, &minus);
- if (r < 0)
- return r;
+ r = parse_sec(t, &minus);
+ if (r < 0)
+ return r;
- goto finish;
+ goto finish;
- } else if ((k = endswith(t, " left"))) {
- t = strndupa(t, k - t);
+ } else if ((k = endswith(t, " left"))) {
+ t = strndupa(t, k - t);
- r = parse_sec(t, &plus);
- if (r < 0)
- return r;
+ r = parse_sec(t, &plus);
+ if (r < 0)
+ return r;
- goto finish;
- }
+ goto finish;
+ }
- /* See if the timestamp is suffixed with UTC */
- utc = endswith_no_case(t, " UTC");
- if (utc)
- t = strndupa(t, utc - t);
- else {
- const char *e = NULL;
- int j;
+ /* See if the timestamp is suffixed with UTC */
+ utc = endswith_no_case(t, " UTC");
+ if (utc)
+ t = strndupa(t, utc - t);
+ else {
+ const char *e = NULL;
+ int j;
- tzset();
+ tzset();
- /* See if the timestamp is suffixed by either the DST or non-DST local timezone. Note that we only
- * support the local timezones here, nothing else. Not because we wouldn't want to, but simply because
- * there are no nice APIs available to cover this. By accepting the local time zone strings, we make
- * sure that all timestamps written by format_timestamp() can be parsed correctly, even though we don't
- * support arbitrary timezone specifications. */
+ /* See if the timestamp is suffixed by either the DST or non-DST local timezone. Note that we only
+ * support the local timezones here, nothing else. Not because we wouldn't want to, but simply because
+ * there are no nice APIs available to cover this. By accepting the local time zone strings, we make
+ * sure that all timestamps written by format_timestamp() can be parsed correctly, even though we don't
+ * support arbitrary timezone specifications. */
- for (j = 0; j <= 1; j++) {
+ for (j = 0; j <= 1; j++) {
- if (isempty(tzname[j]))
- continue;
+ if (isempty(tzname[j]))
+ continue;
- e = endswith_no_case(t, tzname[j]);
- if (!e)
- continue;
- if (e == t)
- continue;
- if (e[-1] != ' ')
- continue;
+ e = endswith_no_case(t, tzname[j]);
+ if (!e)
+ continue;
+ if (e == t)
+ continue;
+ if (e[-1] != ' ')
+ continue;
- break;
- }
+ break;
+ }
- if (IN_SET(j, 0, 1)) {
- /* Found one of the two timezones specified. */
- t = strndupa(t, e - t - 1);
- dst = j;
- tzn = tzname[j];
+ if (IN_SET(j, 0, 1)) {
+ /* Found one of the two timezones specified. */
+ t = strndupa(t, e - t - 1);
+ dst = j;
+ tzn = tzname[j];
+ }
}
}
@@ -733,7 +736,7 @@ int parse_timestamp(const char *t, usec_t *usec) {
return -EINVAL;
tm.tm_isdst = dst;
- if (tzn)
+ if (!with_tz && tzn)
tm.tm_zone = tzn;
if (streq(t, "today")) {
@@ -874,6 +877,67 @@ finish:
return 0;
}
+typedef struct ParseTimestampResult {
+ usec_t usec;
+ int return_value;
+} ParseTimestampResult;
+
+int parse_timestamp(const char *t, usec_t *usec) {
+ char *last_space, *timezone = NULL;
+ ParseTimestampResult *shared, tmp;
+ int r;
+ pid_t pid;
+
+ last_space = strrchr(t, ' ');
+ if (last_space != NULL && timezone_is_valid(last_space + 1))
+ timezone = last_space + 1;
+
+ if (timezone == NULL || endswith_no_case(t, " UTC"))
+ return parse_timestamp_impl(t, usec, false);
+
+ t = strndupa(t, last_space - t);
+
+ shared = mmap(NULL, sizeof *shared, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
+ if (shared == MAP_FAILED)
+ return negative_errno();
+
+ pid = fork();
+
+ if (pid == -1) {
+ int fork_errno = errno;
+ (void) munmap(shared, sizeof *shared);
+ return -fork_errno;
+ }
+
+ if (pid == 0) {
+ if (setenv("TZ", timezone, 1) != 0) {
+ shared->return_value = negative_errno();
+ _exit(EXIT_FAILURE);
+ }
+
+ tzset();
+
+ shared->return_value = parse_timestamp_impl(t, &shared->usec, true);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ r = wait_for_terminate(pid, NULL);
+ if (r < 0) {
+ (void) munmap(shared, sizeof *shared);
+ return r;
+ }
+
+ tmp = *shared;
+ if (munmap(shared, sizeof *shared) != 0)
+ return negative_errno();
+
+ if (tmp.return_value == 0)
+ *usec = tmp.usec;
+
+ return tmp.return_value;
+}
+
static char* extract_multiplier(char *p, usec_t *multiplier) {
static const struct {
const char *suffix;
diff --git a/src/systemd/src/basic/util.c b/src/systemd/src/basic/util.c
index 2f45128ed4..daaee99284 100644
--- a/src/systemd/src/basic/util.c
+++ b/src/systemd/src/basic/util.c
@@ -34,6 +34,7 @@
#include <unistd.h>
#include "alloc-util.h"
+#include "btrfs-util.h"
#include "build.h"
#include "cgroup-util.h"
#include "def.h"
@@ -719,3 +720,133 @@ int version(void) {
SYSTEMD_FEATURES);
return 0;
}
+
+int get_block_device(const char *path, dev_t *dev) {
+ struct stat st;
+ struct statfs sfs;
+
+ assert(path);
+ assert(dev);
+
+ /* Get's the block device directly backing a file system. If
+ * the block device is encrypted, returns the device mapper
+ * block device. */
+
+ if (lstat(path, &st))
+ return -errno;
+
+ if (major(st.st_dev) != 0) {
+ *dev = st.st_dev;
+ return 1;
+ }
+
+ if (statfs(path, &sfs) < 0)
+ return -errno;
+
+ if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
+ return btrfs_get_block_device(path, dev);
+
+ return 0;
+}
+
+int get_block_device_harder(const char *path, dev_t *dev) {
+ _cleanup_closedir_ DIR *d = NULL;
+ _cleanup_free_ char *p = NULL, *t = NULL;
+ struct dirent *de, *found = NULL;
+ const char *q;
+ unsigned maj, min;
+ dev_t dt;
+ int r;
+
+ assert(path);
+ assert(dev);
+
+ /* Gets the backing block device for a file system, and
+ * handles LUKS encrypted file systems, looking for its
+ * immediate parent, if there is one. */
+
+ r = get_block_device(path, &dt);
+ if (r <= 0)
+ return r;
+
+ if (asprintf(&p, "/sys/dev/block/%u:%u/slaves", major(dt), minor(dt)) < 0)
+ return -ENOMEM;
+
+ d = opendir(p);
+ if (!d) {
+ if (errno == ENOENT)
+ goto fallback;
+
+ return -errno;
+ }
+
+ FOREACH_DIRENT_ALL(de, d, return -errno) {
+
+ if (dot_or_dot_dot(de->d_name))
+ continue;
+
+ if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
+ continue;
+
+ if (found) {
+ _cleanup_free_ char *u = NULL, *v = NULL, *a = NULL, *b = NULL;
+
+ /* We found a device backed by multiple other devices. We don't really support automatic
+ * discovery on such setups, with the exception of dm-verity partitions. In this case there are
+ * two backing devices: the data partition and the hash partition. We are fine with such
+ * setups, however, only if both partitions are on the same physical device. Hence, let's
+ * verify this. */
+
+ u = strjoin(p, "/", de->d_name, "/../dev");
+ if (!u)
+ return -ENOMEM;
+
+ v = strjoin(p, "/", found->d_name, "/../dev");
+ if (!v)
+ return -ENOMEM;
+
+ r = read_one_line_file(u, &a);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to read %s: %m", u);
+ goto fallback;
+ }
+
+ r = read_one_line_file(v, &b);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to read %s: %m", v);
+ goto fallback;
+ }
+
+ /* Check if the parent device is the same. If not, then the two backing devices are on
+ * different physical devices, and we don't support that. */
+ if (!streq(a, b))
+ goto fallback;
+ }
+
+ found = de;
+ }
+
+ if (!found)
+ goto fallback;
+
+ q = strjoina(p, "/", found->d_name, "/dev");
+
+ r = read_one_line_file(q, &t);
+ if (r == -ENOENT)
+ goto fallback;
+ if (r < 0)
+ return r;
+
+ if (sscanf(t, "%u:%u", &maj, &min) != 2)
+ return -EINVAL;
+
+ if (maj == 0)
+ goto fallback;
+
+ *dev = makedev(maj, min);
+ return 1;
+
+fallback:
+ *dev = dt;
+ return 1;
+}
diff --git a/src/systemd/src/basic/util.h b/src/systemd/src/basic/util.h
index c7da6c39bf..b31dfd1c92 100644
--- a/src/systemd/src/basic/util.h
+++ b/src/systemd/src/basic/util.h
@@ -192,3 +192,6 @@ uint64_t system_tasks_max_scale(uint64_t v, uint64_t max);
int update_reboot_parameter_and_warn(const char *param);
int version(void);
+
+int get_block_device(const char *path, dev_t *dev);
+int get_block_device_harder(const char *path, dev_t *dev);
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
index e20d339bd5..8426f602a9 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
@@ -62,6 +62,7 @@ struct sd_dhcp_client {
uint8_t *req_opts;
size_t req_opts_allocated;
size_t req_opts_size;
+ bool anonymize;
be32_t last_addr;
uint8_t mac_addr[MAX_MAC_ADDR_LEN];
size_t mac_addr_len;
@@ -116,6 +117,32 @@ static const uint8_t default_req_opts[] = {
SD_DHCP_OPTION_DOMAIN_NAME_SERVER,
};
+/* RFC7844 section 3:
+ MAY contain the Parameter Request List option.
+ RFC7844 section 3.6:
+ The client intending to protect its privacy SHOULD only request a
+ minimal number of options in the PRL and SHOULD also randomly shuffle
+ the ordering of option codes in the PRL. If this random ordering
+ cannot be implemented, the client MAY order the option codes in the
+ PRL by option code number (lowest to highest).
+*/
+/* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
+static const uint8_t default_req_opts_anonymize[] = {
+ SD_DHCP_OPTION_SUBNET_MASK, /* 1 */
+ SD_DHCP_OPTION_ROUTER, /* 3 */
+ SD_DHCP_OPTION_DOMAIN_NAME_SERVER, /* 6 */
+ SD_DHCP_OPTION_DOMAIN_NAME, /* 15 */
+ SD_DHCP_OPTION_ROUTER_DISCOVER, /* 31 */
+ SD_DHCP_OPTION_STATIC_ROUTE, /* 33 */
+ SD_DHCP_OPTION_VENDOR_SPECIFIC, /* 43 */
+ SD_DHCP_OPTION_NETBIOS_NAMESERVER, /* 44 */
+ SD_DHCP_OPTION_NETBIOS_NODETYPE, /* 46 */
+ SD_DHCP_OPTION_NETBIOS_SCOPE, /* 47 */
+ SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE, /* 121 */
+ SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE, /* 249 */
+ SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY, /* 252 */
+};
+
static int client_receive_message_raw(
sd_event_source *s,
int fd,
@@ -588,11 +615,18 @@ static int client_message_init(
it MUST include that list in any subsequent DHCPREQUEST
messages.
*/
- r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
- SD_DHCP_OPTION_PARAMETER_REQUEST_LIST,
- client->req_opts_size, client->req_opts);
- if (r < 0)
- return r;
+
+ /* RFC7844 section 3:
+ MAY contain the Parameter Request List option. */
+ /* NOTE: in case that there would be an option to do not send
+ * any PRL at all, the size should be checked before sending */
+ if (client->req_opts_size > 0) {
+ r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
+ SD_DHCP_OPTION_PARAMETER_REQUEST_LIST,
+ client->req_opts_size, client->req_opts);
+ if (r < 0)
+ return r;
+ }
/* RFC2131 section 3.5:
The client SHOULD include the ’maximum DHCP message size’ option to
@@ -616,12 +650,16 @@ static int client_message_init(
Maximum DHCP Message Size option is the total maximum packet size,
including IP and UDP headers.)
*/
- max_size = htobe16(size);
- r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
- SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
- 2, &max_size);
- if (r < 0)
- return r;
+ /* RFC7844 section 3:
+ SHOULD NOT contain any other option. */
+ if (!client->anonymize) {
+ max_size = htobe16(size);
+ r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
+ SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
+ 2, &max_size);
+ if (r < 0)
+ return r;
+ }
*_optlen = optlen;
*_optoffset = optoffset;
@@ -1783,7 +1821,14 @@ int sd_dhcp_client_start(sd_dhcp_client *client) {
if (r < 0)
return r;
- if (client->last_addr)
+ /* RFC7844 section 3.3:
+ SHOULD perform a complete four-way handshake, starting with a
+ DHCPDISCOVER, to obtain a new address lease. If the client can
+ ascertain that this is exactly the same network to which it was
+ previously connected, and if the link-layer address did not change,
+ the client MAY issue a DHCPREQUEST to try to reclaim the current
+ address. */
+ if (client->last_addr && !client->anonymize)
client->state = DHCP_STATE_INIT_REBOOT;
r = client_start(client);
@@ -1875,7 +1920,7 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
return mfree(client);
}
-int sd_dhcp_client_new(sd_dhcp_client **ret) {
+int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) {
_cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = NULL;
assert_return(ret, -EINVAL);
@@ -1892,8 +1937,15 @@ int sd_dhcp_client_new(sd_dhcp_client **ret) {
client->mtu = DHCP_DEFAULT_MIN_SIZE;
client->port = DHCP_PORT_CLIENT;
- client->req_opts_size = ELEMENTSOF(default_req_opts);
- client->req_opts = memdup(default_req_opts, client->req_opts_size);
+ client->anonymize = !!anonymize;
+ /* NOTE: this could be moved to a function. */
+ if (anonymize) {
+ client->req_opts_size = ELEMENTSOF(default_req_opts_anonymize);
+ client->req_opts = memdup(default_req_opts_anonymize, client->req_opts_size);
+ } else {
+ client->req_opts_size = ELEMENTSOF(default_req_opts);
+ client->req_opts = memdup(default_req_opts, client->req_opts_size);
+ }
if (!client->req_opts)
return -ENOMEM;
diff --git a/src/systemd/src/systemd/sd-dhcp-client.h b/src/systemd/src/systemd/sd-dhcp-client.h
index f731fdcbd4..5e46d8d0e8 100644
--- a/src/systemd/src/systemd/sd-dhcp-client.h
+++ b/src/systemd/src/systemd/sd-dhcp-client.h
@@ -58,9 +58,17 @@ enum {
SD_DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT = 24,
SD_DHCP_OPTION_INTERFACE_MTU = 26,
SD_DHCP_OPTION_BROADCAST = 28,
+ /* Windows 10 option to send when Anonymize=true */
+ SD_DHCP_OPTION_ROUTER_DISCOVER = 31,
SD_DHCP_OPTION_STATIC_ROUTE = 33,
SD_DHCP_OPTION_NTP_SERVER = 42,
SD_DHCP_OPTION_VENDOR_SPECIFIC = 43,
+ /* Windows 10 option to send when Anonymize=true */
+ SD_DHCP_OPTION_NETBIOS_NAMESERVER = 44,
+ /* Windows 10 option to send when Anonymize=true */
+ SD_DHCP_OPTION_NETBIOS_NODETYPE = 46,
+ /* Windows 10 option to send when Anonymize=true */
+ SD_DHCP_OPTION_NETBIOS_SCOPE = 47,
SD_DHCP_OPTION_REQUESTED_IP_ADDRESS = 50,
SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME = 51,
SD_DHCP_OPTION_OVERLOAD = 52,
@@ -79,6 +87,10 @@ enum {
SD_DHCP_OPTION_DOMAIN_SEARCH_LIST = 119,
SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE = 121,
SD_DHCP_OPTION_PRIVATE_BASE = 224,
+ /* Windows 10 option to send when Anonymize=true */
+ SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE = 249,
+ /* Windows 10 option to send when Anonymize=true */
+ SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY = 252,
SD_DHCP_OPTION_PRIVATE_LAST = 254,
SD_DHCP_OPTION_END = 255,
};
@@ -146,7 +158,9 @@ int sd_dhcp_client_start(sd_dhcp_client *client);
sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client);
sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client);
-int sd_dhcp_client_new(sd_dhcp_client **ret);
+/* NOTE: anonymize parameter is used to initialize PRL memory with different
+ * options when using RFC7844 Anonymity Profiles */
+int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize);
int sd_dhcp_client_attach_event(
sd_dhcp_client *client,