diff options
author | Thomas Haller <thaller@redhat.com> | 2017-09-21 10:38:52 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2017-09-21 15:08:50 +0200 |
commit | eba874f859945a7a9aa22735cd20b144dc0eb918 (patch) | |
tree | 8bffe675876603a5f189f7d21a1c176cc59f09c8 | |
parent | 770ad94cba6aa925f263cf75715d42ef424da68e (diff) | |
download | NetworkManager-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.c | 4 | ||||
-rw-r--r-- | src/systemd/src/basic/fs-util.h | 1 | ||||
-rw-r--r-- | src/systemd/src/basic/process-util.c | 26 | ||||
-rw-r--r-- | src/systemd/src/basic/process-util.h | 1 | ||||
-rw-r--r-- | src/systemd/src/basic/time-util.c | 182 | ||||
-rw-r--r-- | src/systemd/src/basic/util.c | 131 | ||||
-rw-r--r-- | src/systemd/src/basic/util.h | 3 | ||||
-rw-r--r-- | src/systemd/src/libsystemd-network/sd-dhcp-client.c | 82 | ||||
-rw-r--r-- | src/systemd/src/systemd/sd-dhcp-client.h | 16 |
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, |