From de8d6e5563310e7ae992fb00ad83fcbcfbac5cb5 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Mon, 30 Mar 2020 16:30:46 +0200 Subject: [PATCH 1/2] sd-dhcpv6: Add support to set request MUD URL --- src/libsystemd-network/sd-dhcp6-client.c | 46 ++++++++++++++++++++++++ src/systemd/sd-dhcp6-client.h | 4 +++ 2 files changed, 50 insertions(+) diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index eac2e725cce..3f6caedfdfa 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -25,6 +25,7 @@ #include "socket-util.h" #include "string-table.h" #include "util.h" +#include "web-util.h" #define MAX_MAC_ADDR_LEN INFINIBAND_ALEN @@ -65,6 +66,7 @@ struct sd_dhcp6_client { size_t req_opts_allocated; size_t req_opts_len; char *fqdn; + char *mudurl; sd_event_source *receive_message; usec_t retransmit_time; uint8_t retransmit_count; @@ -363,6 +365,17 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) return 0; } +int sd_dhcp6_client_set_request_mud_url(sd_dhcp6_client *client, char *mudurl) { + + assert_return(client, -EINVAL); + assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY); + assert_return(mudurl, -EINVAL); + assert_return(strlen(mudurl) <= 255, -EINVAL); + assert_return(http_url_is_valid(mudurl), -EINVAL); + + return free_and_strdup(&client->mudurl, mudurl); +} + int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client, int *delegation) { assert_return(client, -EINVAL); assert_return(delegation, -EINVAL); @@ -484,6 +497,14 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { case DHCP6_STATE_INFORMATION_REQUEST: message->type = DHCP6_INFORMATION_REQUEST; + if (client->mudurl) { + r = dhcp6_option_append(&opt, &optlen, + SD_DHCP6_OPTION_MUD_URL, strlen(client->mudurl), + client->mudurl); + if (r < 0) + return r; + } + break; case DHCP6_STATE_SOLICITATION: @@ -507,6 +528,14 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { return r; } + if (client->mudurl) { + r = dhcp6_option_append(&opt, &optlen, + SD_DHCP6_OPTION_MUD_URL, strlen(client->mudurl), + client->mudurl); + if (r < 0) + return r; + } + if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) { r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd, &client->hint_pd_prefix); if (r < 0) @@ -545,6 +574,14 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { return r; } + if (client->mudurl) { + r = dhcp6_option_append(&opt, &optlen, + SD_DHCP6_OPTION_MUD_URL, strlen(client->mudurl), + client->mudurl); + if (r < 0) + return r; + } + if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) { r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL); if (r < 0) @@ -571,6 +608,14 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { return r; } + if (client->mudurl) { + r = dhcp6_option_append(&opt, &optlen, + SD_DHCP6_OPTION_MUD_URL, strlen(client->mudurl), + client->mudurl); + if (r < 0) + return r; + } + if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) { r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL); if (r < 0) @@ -1521,6 +1566,7 @@ static sd_dhcp6_client *dhcp6_client_free(sd_dhcp6_client *client) { free(client->req_opts); free(client->fqdn); + free(client->mudurl); return mfree(client); } diff --git a/src/systemd/sd-dhcp6-client.h b/src/systemd/sd-dhcp6-client.h index be34d43e748..42d4ec752c3 100644 --- a/src/systemd/sd-dhcp6-client.h +++ b/src/systemd/sd-dhcp6-client.h @@ -73,6 +73,7 @@ enum { SD_DHCP6_OPTION_FQDN = 39, /* RFC 4704 */ SD_DHCP6_OPTION_NTP_SERVER = 56, /* RFC 5908 */ + SD_DHCP6_OPTION_MUD_URL = 112, /* RFC 8250 */ /* option codes 89-142 are unassigned */ /* option codes 144-65535 are unassigned */ @@ -120,6 +121,9 @@ int sd_dhcp6_client_get_information_request( int sd_dhcp6_client_set_request_option( sd_dhcp6_client *client, uint16_t option); +int sd_dhcp6_client_set_request_mud_url( + sd_dhcp6_client *client, + char *mudurl); int sd_dhcp6_client_set_prefix_delegation_hint( sd_dhcp6_client *client, uint8_t prefixlen, From 3175a8c21bc2c40f4f43c3b7e42203af2898a93a Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Mon, 30 Mar 2020 16:31:10 +0200 Subject: [PATCH 2/2] network: DHCPv6 Add support to send MUD URL --- man/systemd.network.xml | 10 +++++ src/network/networkd-dhcp-common.c | 43 +++++++++++++++++++ src/network/networkd-dhcp-common.h | 1 + src/network/networkd-dhcp6.c | 6 +++ src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.c | 1 + src/network/networkd-network.h | 1 + .../fuzz-network-parser/directives.network | 1 + 8 files changed, 64 insertions(+) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 5457e668dd2..201e33ed6e0 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -1691,6 +1691,16 @@ + + MUDURL= + + When configured, the Manufacturer Usage Descriptions (MUD) URL will be sent to the DHCPV6 server. + Takes an URL of length up to 255 characters. A superficial verification that the string is a valid URL + will be performed. DHCPv6 clients are intended to have at most one MUD URL associated with them. See + RFC 8520. + + + ForceDHCPv6PDOtherInformation= diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c index 8664d8cdc0d..0473aba6159 100644 --- a/src/network/networkd-dhcp-common.c +++ b/src/network/networkd-dhcp-common.c @@ -8,6 +8,7 @@ #include "parse-util.h" #include "string-table.h" #include "strv.h" +#include "web-util.h" int config_parse_dhcp( const char* unit, @@ -265,6 +266,48 @@ int config_parse_dhcp6_pd_hint( return 0; } +int config_parse_dhcp6_mud_url( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *unescaped = NULL; + Network *network = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + network->dhcp6_mudurl = mfree(network->dhcp6_mudurl); + return 0; + } + + r = cunescape(rvalue, 0, &unescaped); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to Failed to unescape MUD URL, ignoring: %s", rvalue); + return 0; + } + + if (!http_url_is_valid(unescaped) || strlen(unescaped) > 255) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Failed to parse MUD URL '%s', ignoring: %m", rvalue); + + return 0; + } + + return free_and_replace(network->dhcp6_mudurl, unescaped); +} + int config_parse_dhcp_send_option( const char *unit, const char *filename, diff --git a/src/network/networkd-dhcp-common.h b/src/network/networkd-dhcp-common.h index 1d6ddbb8cc0..ca86016ef2a 100644 --- a/src/network/networkd-dhcp-common.h +++ b/src/network/networkd-dhcp-common.h @@ -48,4 +48,5 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_sip); CONFIG_PARSER_PROTOTYPE(config_parse_iaid); CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_hint); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_mud_url); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_send_option); diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 7304270c60b..3580498e351 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -676,6 +676,12 @@ int dhcp6_configure(Link *link) { return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set request flag for rapid commit: %m"); } + if (link->network->dhcp6_mudurl) { + r = sd_dhcp6_client_set_request_mud_url(client, link->network->dhcp6_mudurl); + if (r < 0) + return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set MUD URL: %m"); + } + r = sd_dhcp6_client_set_callback(client, dhcp6_handler, link); if (r < 0) return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set callback: %m"); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index fd996327a55..d98b32b7568 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -189,6 +189,7 @@ DHCPv4.RouteMTUBytes, config_parse_mtu, DHCPv6.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp6_use_dns) DHCPv6.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp6_use_ntp) DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, rapid_commit) +DHCPv6.MUDURL, config_parse_dhcp6_mud_url, 0, 0 DHCPv6.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information) DHCPv6.PrefixDelegationHint, config_parse_dhcp6_pd_hint, 0, 0 DHCPv6.WithoutRA, config_parse_bool, 0, offsetof(Network, dhcp6_without_ra) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index e7ead446c76..46a5a5320a0 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -644,6 +644,7 @@ static Network *network_free(Network *network) { set_free(network->dhcp_black_listed_ip); set_free(network->dhcp_request_options); free(network->mac); + free(network->dhcp6_mudurl); if (network->dhcp_acd) sd_ipv4acd_unref(network->dhcp_acd); diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index f747ccaf101..3b48e4238dc 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -130,6 +130,7 @@ struct Network { bool dhcp6_use_ntp; bool dhcp6_without_ra; uint8_t dhcp6_pd_length; + char *dhcp6_mudurl; struct in6_addr dhcp6_pd_address; /* DHCP Server Support */ diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 4418fc01495..76a4c42403c 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -110,6 +110,7 @@ RapidCommit= ForceDHCPv6PDOtherInformation= PrefixDelegationHint= WithoutRA= +MUDURL= [Route] Destination= Protocol=