From db3d23582080d1f8f039678e616591e34c59c10a Mon Sep 17 00:00:00 2001 From: juga0 Date: Thu, 3 Aug 2017 03:32:46 +0200 Subject: [PATCH] networkd: set PRL default options depending on Anonymize. Add also Client variable to know when Anonymize is true. --- src/libsystemd-network/sd-dhcp-client.c | 40 ++++++++++++++++++++++++++++--- src/libsystemd-network/test-dhcp-client.c | 22 +++++++++++------ src/network/networkd-dhcp4.c | 2 +- src/network/networkd-link.c | 2 +- src/systemd/sd-dhcp-client.h | 4 +++- 5 files changed, 57 insertions(+), 13 deletions(-) diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index e20d339..9cc5636 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/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, @@ -1875,7 +1902,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 +1919,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/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c index f5f1284..4eaebbb 100644 --- a/src/libsystemd-network/test-dhcp-client.c +++ b/src/libsystemd-network/test-dhcp-client.c @@ -56,7 +56,8 @@ static void test_request_basic(sd_event *e) { if (verbose) printf("* %s\n", __FUNCTION__); - r = sd_dhcp_client_new(&client); + /* Initialize client without Anonymize settings. */ + r = sd_dhcp_client_new(&client, false); assert_se(r >= 0); assert_se(client); @@ -78,6 +79,8 @@ static void test_request_basic(sd_event *e) { SD_DHCP_OPTION_SUBNET_MASK) == -EEXIST); assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_ROUTER) == -EEXIST); + /* This PRL option is not set when using Anonymize, but in this test + * Anonymize settings are not being used. */ assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_HOST_NAME) == -EEXIST); assert_se(sd_dhcp_client_set_request_option(client, @@ -97,10 +100,15 @@ static void test_request_basic(sd_event *e) { SD_DHCP_OPTION_PARAMETER_REQUEST_LIST) == -EINVAL); - assert_se(sd_dhcp_client_set_request_option(client, 33) == 0); - assert_se(sd_dhcp_client_set_request_option(client, 33) == -EEXIST); - assert_se(sd_dhcp_client_set_request_option(client, 44) == 0); - assert_se(sd_dhcp_client_set_request_option(client, 33) == -EEXIST); + /* RFC7844: option 33 (SD_DHCP_OPTION_STATIC_ROUTE) is set in the + * default PRL when using Anonymize, so it is changed to other option + * that is not set by default, to check that it succed setting it. + * Ooptions not set by default (using or not anonymize) are option 17 + * (SD_DHCP_OPTION_ROOT_PATH) and 42 (SD_DHCP_OPTION_NTP_SERVER) */ + assert_se(sd_dhcp_client_set_request_option(client, 17) == 0); + assert_se(sd_dhcp_client_set_request_option(client, 17) == -EEXIST); + assert_se(sd_dhcp_client_set_request_option(client, 42) == 0); + assert_se(sd_dhcp_client_set_request_option(client, 17) == -EEXIST); sd_dhcp_client_unref(client); } @@ -236,7 +244,7 @@ static void test_discover_message(sd_event *e) { if (verbose) printf("* %s\n", __FUNCTION__); - r = sd_dhcp_client_new(&client); + r = sd_dhcp_client_new(&client, false); assert_se(r >= 0); assert_se(client); @@ -451,7 +459,7 @@ static void test_addr_acq(sd_event *e) { if (verbose) printf("* %s\n", __FUNCTION__); - r = sd_dhcp_client_new(&client); + r = sd_dhcp_client_new(&client, false); assert_se(r >= 0); assert_se(client); diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 546c90b..07661e3 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -583,7 +583,7 @@ int dhcp4_configure(Link *link) { assert(link->network->dhcp & ADDRESS_FAMILY_IPV4); if (!link->dhcp_client) { - r = sd_dhcp_client_new(&link->dhcp_client); + r = sd_dhcp_client_new(&link->dhcp_client, link->network->dhcp_anonymize); if (r < 0) return r; } diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 2ad10d2..2fb1dd6 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2916,7 +2916,7 @@ network_file_fail: goto dhcp4_address_fail; } - r = sd_dhcp_client_new(&link->dhcp_client); + r = sd_dhcp_client_new(&link->dhcp_client, link->network->dhcp_anonymize); if (r < 0) return log_link_error_errno(link, r, "Failed to create DHCPv4 client: %m"); diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h index fa7e80d..5e46d8d 100644 --- a/src/systemd/sd-dhcp-client.h +++ b/src/systemd/sd-dhcp-client.h @@ -158,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, -- 2.7.4