diff --git a/src/libsystemd-network/dhcp-client-internal.h b/src/libsystemd-network/dhcp-client-internal.h index 7db0a91fa9..9e4d0dac86 100644 --- a/src/libsystemd-network/dhcp-client-internal.h +++ b/src/libsystemd-network/dhcp-client-internal.h @@ -78,9 +78,8 @@ struct sd_dhcp_client { void *state_userdata; sd_dhcp_lease *lease; usec_t start_delay; - int ip_service_type; + uint8_t ip_service_type; int socket_priority; - bool socket_priority_set; bool ipv6_acquired; bool bootp; bool send_release; diff --git a/src/libsystemd-network/dhcp-client-send.c b/src/libsystemd-network/dhcp-client-send.c index e8b91a3e7c..a77f3c2ae7 100644 --- a/src/libsystemd-network/dhcp-client-send.c +++ b/src/libsystemd-network/dhcp-client-send.c @@ -93,7 +93,7 @@ static int client_send_raw( &client->bcast_addr, client->arp_type, client->port, - client->socket_priority_set, + /* so_priority_set= */ true, client->socket_priority); if (fd < 0) return fd; diff --git a/src/libsystemd-network/fuzz-dhcp-client.c b/src/libsystemd-network/fuzz-dhcp-client.c index bc6be37be8..074b52b7c0 100644 --- a/src/libsystemd-network/fuzz-dhcp-client.c +++ b/src/libsystemd-network/fuzz-dhcp-client.c @@ -54,7 +54,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ASSERT_NOT_NULL(e); _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = NULL; - ASSERT_OK(sd_dhcp_client_new(&client, /* anonymize= */ false)); + ASSERT_OK(sd_dhcp_client_new(&client)); ASSERT_NOT_NULL(client); ASSERT_OK(sd_dhcp_client_attach_event(client, e, /* priority= */ 0)); diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 10161148a4..5b17a56a4d 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -22,6 +22,7 @@ #include "network-common.h" #include "random-util.h" #include "set.h" +#include "socket-util.h" #include "string-table.h" #include "string-util.h" #include "time-util.h" @@ -45,32 +46,6 @@ 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_DISCOVERY, /* 31 */ - SD_DHCP_OPTION_STATIC_ROUTE, /* 33 */ - SD_DHCP_OPTION_VENDOR_SPECIFIC_INFORMATION, /* 43 */ - SD_DHCP_OPTION_NETBIOS_NAME_SERVER, /* 44 */ - SD_DHCP_OPTION_NETBIOS_NODE_TYPE, /* 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 void client_stop(sd_dhcp_client *client, int error); static int client_restart(sd_dhcp_client *client); @@ -100,6 +75,14 @@ int sd_dhcp_client_set_callback( return 0; } +int sd_dhcp_client_set_anonymize(sd_dhcp_client *client, int b) { + assert_return(client, -EINVAL); + assert_return(!sd_dhcp_client_is_running(client), -EBUSY); + + client->anonymize = !!b; + return 0; +} + int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast) { assert_return(client, -EINVAL); assert_return(!sd_dhcp_client_is_running(client), -EBUSY); @@ -533,7 +516,7 @@ int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) { return 0; } -int sd_dhcp_client_set_service_type(sd_dhcp_client *client, int type) { +int sd_dhcp_client_set_ip_service_type(sd_dhcp_client *client, uint8_t type) { assert_return(client, -EINVAL); assert_return(!sd_dhcp_client_is_running(client), -EBUSY); @@ -546,7 +529,6 @@ int sd_dhcp_client_set_socket_priority(sd_dhcp_client *client, int socket_priori assert_return(client, -EINVAL); assert_return(!sd_dhcp_client_is_running(client), -EBUSY); - client->socket_priority_set = true; client->socket_priority = socket_priority; return 0; @@ -1427,9 +1409,7 @@ static sd_dhcp_client* dhcp_client_free(sd_dhcp_client *client) { DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client, sd_dhcp_client, dhcp_client_free); -int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) { - const uint8_t *opts; - size_t n_opts; +int sd_dhcp_client_new(sd_dhcp_client **ret) { int r; assert_return(ret, -EINVAL); @@ -1444,21 +1424,13 @@ int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) { .ifindex = -1, .port = DHCP_PORT_CLIENT, .server_port = DHCP_PORT_SERVER, - .anonymize = !!anonymize, .max_discover_attempts = UINT64_MAX, - .ip_service_type = -1, + .ip_service_type = IPTOS_CLASS_CS6, /* Defaults to CS6 (Internetwork Control). */ + .socket_priority = tos_to_priority(IPTOS_CLASS_CS6), }; - /* NOTE: this could be moved to a function. */ - if (anonymize) { - n_opts = ELEMENTSOF(default_req_opts_anonymize); - opts = default_req_opts_anonymize; - } else { - n_opts = ELEMENTSOF(default_req_opts); - opts = default_req_opts; - } - for (size_t i = 0; i < n_opts; i++) { - r = sd_dhcp_client_set_request_option(client, opts[i]); + FOREACH_ELEMENT(opt, default_req_opts) { + r = sd_dhcp_client_set_request_option(client, *opt); if (r < 0) return r; } diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c index c62f46222a..97803a7faf 100644 --- a/src/libsystemd-network/test-dhcp-client.c +++ b/src/libsystemd-network/test-dhcp-client.c @@ -48,7 +48,7 @@ static be32_t xid; TEST(dhcp_client_setters) { /* Initialize client without Anonymize settings. */ _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = NULL; - ASSERT_OK(sd_dhcp_client_new(&client, /* anonymize= */ false)); + ASSERT_OK(sd_dhcp_client_new(&client)); ASSERT_NOT_NULL(client); ASSERT_RETURN_EXPECTED_SE(sd_dhcp_client_set_request_option(NULL, 0) == -EINVAL); @@ -91,15 +91,15 @@ TEST(dhcp_client_setters) { ASSERT_OK_ZERO(sd_dhcp_client_set_request_option(client, 17)); } -TEST(dhcp_client_anonymize) { +TEST(dhcp_client_set_anonymize) { /* Initialize client with Anonymize settings. */ _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = NULL; - ASSERT_OK(sd_dhcp_client_new(&client, /* anonymize= */ true)); + ASSERT_OK(sd_dhcp_client_new(&client)); + ASSERT_OK(sd_dhcp_client_set_anonymize(client, true)); ASSERT_NOT_NULL(client); - ASSERT_OK_ZERO(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_NETBIOS_NAME_SERVER)); - /* This PRL option is not set when using Anonymize */ - ASSERT_OK_POSITIVE(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_HOST_NAME)); + ASSERT_OK_POSITIVE(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_NETBIOS_NAME_SERVER)); + ASSERT_OK_ZERO(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_HOST_NAME)); ASSERT_ERROR(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST), EINVAL); /* RFC7844: option 101 (SD_DHCP_OPTION_NEW_TZDB_TIMEZONE) is not set in the @@ -211,7 +211,7 @@ TEST(discover_message) { ASSERT_NOT_NULL(e); _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = NULL; - ASSERT_OK(sd_dhcp_client_new(&client, /* anonymize= */ false)); + ASSERT_OK(sd_dhcp_client_new(&client)); ASSERT_NOT_NULL(client); ASSERT_OK(sd_dhcp_client_attach_event(client, e, /* priority= */ 0)); @@ -400,7 +400,7 @@ TEST(addr_acq) { ASSERT_NOT_NULL(e); _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = NULL; - ASSERT_OK(sd_dhcp_client_new(&client, /* anonymize= */ false)); + ASSERT_OK(sd_dhcp_client_new(&client)); ASSERT_NOT_NULL(client); ASSERT_OK(sd_dhcp_client_attach_event(client, e, /* priority= */ 0)); @@ -575,7 +575,7 @@ static void test_bootp_one(void) { ASSERT_NOT_NULL(e); _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = NULL; - ASSERT_OK(sd_dhcp_client_new(&client, /* anonymize= */ false)); + ASSERT_OK(sd_dhcp_client_new(&client)); ASSERT_NOT_NULL(client); ASSERT_OK(sd_dhcp_client_attach_event(client, e, /* priority= */ 0)); diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index b5210e9ddf..468c3eb920 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include +#include #include #include #include @@ -1486,10 +1487,14 @@ static int dhcp4_configure(Link *link) { if (link->dhcp_client) return log_link_debug_errno(link, SYNTHETIC_ERRNO(EBUSY), "DHCPv4 client is already configured."); - r = sd_dhcp_client_new(&link->dhcp_client, link->network->dhcp_anonymize); + r = sd_dhcp_client_new(&link->dhcp_client); if (r < 0) return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to allocate DHCPv4 client: %m"); + r = sd_dhcp_client_set_anonymize(link->dhcp_client, link->network->dhcp_anonymize); + if (r < 0) + return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to anonymize requests: %m"); + r = sd_dhcp_client_set_bootp(link->dhcp_client, link->network->dhcp_use_bootp); if (r < 0) return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to %s BOOTP: %m", @@ -1666,12 +1671,13 @@ static int dhcp4_configure(Link *link) { } if (link->network->dhcp_ip_service_type >= 0) { - r = sd_dhcp_client_set_service_type(link->dhcp_client, link->network->dhcp_ip_service_type); + assert(link->network->dhcp_ip_service_type <= UINT8_MAX); + r = sd_dhcp_client_set_ip_service_type(link->dhcp_client, link->network->dhcp_ip_service_type); if (r < 0) return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to set IP service type: %m"); } - if (link->network->dhcp_socket_priority_set) { + if (link->network->dhcp_socket_priority >= 0) { r = sd_dhcp_client_set_socket_priority(link->dhcp_client, link->network->dhcp_socket_priority); if (r < 0) return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to set socket priority: %m"); @@ -2001,14 +2007,13 @@ int config_parse_dhcp_socket_priority( void *data, void *userdata) { - Network *network = ASSERT_PTR(data); - int a, r; + int r, a, *priority = ASSERT_PTR(data); assert(lvalue); assert(rvalue); if (isempty(rvalue)) { - network->dhcp_socket_priority_set = false; + *priority = -1; return 0; } @@ -2018,10 +2023,13 @@ int config_parse_dhcp_socket_priority( "Failed to parse socket priority, ignoring: %s", rvalue); return 0; } + if (a < 0 || a > TC_PRIO_MAX) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Invalid socket priority, must be in 0…%i, ignoring: %i", TC_PRIO_MAX, a); + return 0; + } - network->dhcp_socket_priority_set = true; - network->dhcp_socket_priority = a; - + *priority = a; return 0; } diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index b925cd3a2b..a5afeed1cb 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -292,7 +292,7 @@ DHCPv4.SendDecline, config_parse_bool, DHCPv4.DenyList, config_parse_in_addr_prefixes, AF_INET, offsetof(Network, dhcp_deny_listed_ip) DHCPv4.AllowList, config_parse_in_addr_prefixes, AF_INET, offsetof(Network, dhcp_allow_listed_ip) DHCPv4.IPServiceType, config_parse_dhcp_ip_service_type, 0, offsetof(Network, dhcp_ip_service_type) -DHCPv4.SocketPriority, config_parse_dhcp_socket_priority, 0, 0 +DHCPv4.SocketPriority, config_parse_dhcp_socket_priority, 0, offsetof(Network, dhcp_socket_priority) DHCPv4.SendOption, config_parse_dhcp_option_tlv, 0, offsetof(Network, dhcp_extra_options) DHCPv4.SendVendorOption, config_parse_dhcp_option_tlv, 0, offsetof(Network, dhcp_vendor_options) DHCPv4.RouteMTUBytes, config_parse_mtu, AF_INET, offsetof(Network, dhcp_route_mtu) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 5cd47ca0a8..17cf78db37 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -404,6 +404,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi .dhcp_client_identifier = _DHCP_CLIENT_ID_INVALID, .dhcp_route_table = RT_TABLE_MAIN, .dhcp_ip_service_type = -1, + .dhcp_socket_priority = -1, .dhcp_broadcast = -1, .dhcp_ipv6_only_mode = -1, .dhcp_6rd_prefix_route_type = RTN_UNREACHABLE, diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index c4020a4341..d1765a2bf4 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -140,7 +140,6 @@ typedef struct Network { int dhcp_critical; int dhcp_ip_service_type; int dhcp_socket_priority; - bool dhcp_socket_priority_set; bool dhcp_anonymize; bool dhcp_send_hostname; bool dhcp_send_hostname_set; diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h index 4e7e79da65..c0216d3638 100644 --- a/src/systemd/sd-dhcp-client.h +++ b/src/systemd/sd-dhcp-client.h @@ -50,7 +50,7 @@ int sd_dhcp_client_set_callback( sd_dhcp_client *client, sd_dhcp_client_callback_t cb, void *userdata); - +int sd_dhcp_client_set_anonymize(sd_dhcp_client *client, int b); int sd_dhcp_client_set_request_option( sd_dhcp_client *client, uint8_t option); @@ -132,9 +132,9 @@ int sd_dhcp_client_set_mud_url( int sd_dhcp_client_get_lease( sd_dhcp_client *client, sd_dhcp_lease **ret); -int sd_dhcp_client_set_service_type( +int sd_dhcp_client_set_ip_service_type( sd_dhcp_client *client, - int type); + uint8_t type); int sd_dhcp_client_set_socket_priority( sd_dhcp_client *client, int socket_priority); @@ -156,9 +156,7 @@ int sd_dhcp_client_is_waiting_for_ipv6_connectivity(sd_dhcp_client *client); _SD_DECLARE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client); -/* 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_new(sd_dhcp_client **ret); int sd_dhcp_client_attach_event( sd_dhcp_client *client,