net/dhcpv6: Add DHCPv6 option for MUD URL (RFC 8520)

Co-Authored-By: Jens Bücker <48720000+jbueck@users.noreply.github.com>
Co-Authored-By: mauspr <75017188+mauspr@users.noreply.github.com>
Co-Authored-By: schulztr <75017039+schulztr@users.noreply.github.com>
This commit is contained in:
Jan Romann 2020-11-25 14:46:54 +01:00
parent 09defe017f
commit 2a570cb957
6 changed files with 89 additions and 3 deletions

View File

@ -26,6 +26,7 @@ PSEUDOMODULES += evtimer_mbox
PSEUDOMODULES += evtimer_on_ztimer
PSEUDOMODULES += fmt_%
PSEUDOMODULES += gnrc_dhcpv6_%
PSEUDOMODULES += gnrc_dhcpv6_client_mud_url
PSEUDOMODULES += gnrc_ipv6_default
PSEUDOMODULES += gnrc_ipv6_ext_frag_stats
PSEUDOMODULES += gnrc_ipv6_router

View File

@ -69,6 +69,7 @@ extern "C" {
* delegation (IA_PD) option */
#define DHCPV6_OPT_IAPFX (26U) /**< IA prefix option */
#define DHCPV6_OPT_SMR (82U) /**< SOL_MAX_RT option */
#define DHCPV6_OPT_MUD_URL (112U) /**< MUD URL option (see RFC 8520) */
/** @} */
/**

View File

@ -45,7 +45,7 @@ extern "C" {
* @brief Static length of the DUID
*/
#define DHCPV6_CLIENT_DUID_LEN (sizeof(dhcpv6_duid_l2_t) + 8U)
#define DHCPV6_CLIENT_BUFLEN (256) /**< length for send and receive buffer */
#define DHCPV6_CLIENT_BUFLEN (256) /**< default length for send and receive buffer */
/**
* @defgroup net_dhcpv6_conf DHCPv6 client compile configurations
@ -58,6 +58,15 @@ extern "C" {
#ifndef CONFIG_DHCPV6_CLIENT_PFX_LEASE_MAX
#define CONFIG_DHCPV6_CLIENT_PFX_LEASE_MAX (1U)
#endif
/**
* @brief MUD URL (must use the https:// scheme)
* For more info, see the [definitions](@ref net_dhcpv6_mud_url_option) below
*/
#ifndef CONFIG_DHCPV6_CLIENT_MUD_URL
#define CONFIG_DHCPV6_CLIENT_MUD_URL "https://example.org"
#endif
/** @} */
/**
@ -167,6 +176,31 @@ uint32_t dhcpv6_client_prefix_valid_until(unsigned netif,
unsigned pfx_len);
/** @} */
/**
* @name DHCPv6 Manufacturer Usage Description (MUD) URL option definitions
* @see [RFC 8520, section 10](https://tools.ietf.org/html/rfc8520#section-10)
* @anchor net_dhcpv6_mud_url_option
* @{
*/
/**
* @brief Length for the send buffer if a MUD URL is included in the DHCP client's packets
*
* @note Only (re)defined by the `gnrc_dhcpv6_client_mud_url` pseudo-module.
*/
#if defined(MODULE_GNRC_DHCPV6_CLIENT_MUD_URL) || defined(DOXYGEN)
#define DHCPV6_CLIENT_SEND_BUFLEN (DHCPV6_CLIENT_BUFLEN + 256)
#else
#define DHCPV6_CLIENT_SEND_BUFLEN (DHCPV6_CLIENT_BUFLEN)
#endif
/**
* @brief Maximal length of a MUD URL
*/
#define MAX_MUD_URL_LENGTH (0xFF - sizeof(dhcpv6_opt_mud_url_t))
/** @} */
#ifdef __cplusplus
}
#endif

View File

@ -16,4 +16,19 @@ config DHCPV6_CLIENT_PFX_LEASE_MAX
int "Maximum number of prefix leases to be stored"
default 1
menuconfig KCONFIG_USEMODULE_GNRC_DHCPV6_CLIENT_MUD_URL
bool "Enable DHCPv6 Client MUD URL"
help
Enable the inclusion of a MUD URL in DHCPv6 packets
as specified in RFC 8520, section 10. This URL
has to point to a MUD file containing YANG-based JSON
with a description of the device and its suggested
network behavior. The URL must use the "https" scheme.
if KCONFIG_USEMODULE_GNRC_DHCPV6_CLIENT_MUD_URL
config CONFIG_DHCPV6_CLIENT_MUD_URL
string "URL pointing to a Manufacturer Usage Description file"
endif # KCONFIG_USEMODULE_GNRC_DHCPV6_CLIENT_MUD_URL
endif # KCONFIG_USEMODULE_DHCPv6

View File

@ -28,7 +28,6 @@
extern "C" {
#endif
/**
* @name DHCPv6 multicast addresses
* @see [RFC 8415, section 7.1]
@ -214,6 +213,17 @@ typedef struct __attribute__((packed)) {
network_uint32_t value; /**< overriding value for SOL_MAX_RT (in sec) */
} dhcpv6_opt_smr_t;
/**
* @brief MUD URL DHCPv6 option format
* @see [RFC 8520, section 10]
* (https://tools.ietf.org/html/rfc8520#section-10)
*/
typedef struct __attribute__((packed)) {
network_uint16_t type; /**< @ref DHCPV6_OPT_MUD_URL */
network_uint16_t len; /**< length of the MUDstring in octets. */
char mudString[]; /**< MUD URL using the "https" scheme */
} dhcpv6_opt_mud_url_t;
#ifdef __cplusplus
}
#endif

View File

@ -65,7 +65,7 @@ typedef struct {
uint8_t duid_len;
} server_t;
static uint8_t send_buf[DHCPV6_CLIENT_BUFLEN];
static uint8_t send_buf[DHCPV6_CLIENT_SEND_BUFLEN];
static uint8_t recv_buf[DHCPV6_CLIENT_BUFLEN];
static uint8_t best_adv[DHCPV6_CLIENT_BUFLEN];
static uint8_t duid[DHCPV6_CLIENT_DUID_LEN];
@ -247,6 +247,22 @@ static inline size_t _compose_elapsed_time_opt(dhcpv6_opt_elapsed_time_t *time)
return len + sizeof(dhcpv6_opt_t);
}
static inline size_t _compose_mud_url_opt(dhcpv6_opt_mud_url_t *mud_url_opt,
const char *mud_url, size_t len_max)
{
uint16_t len = strlen(mud_url);
if (len > len_max) {
assert(0);
return 0;
}
mud_url_opt->type = byteorder_htons(DHCPV6_OPT_MUD_URL);
mud_url_opt->len = byteorder_htons(len);
strncpy(mud_url_opt->mudString, mud_url, len_max);
return len + sizeof(dhcpv6_opt_mud_url_t);
}
static inline size_t _compose_oro_opt(dhcpv6_opt_oro_t *oro, uint16_t *opts,
unsigned opts_num)
{
@ -707,6 +723,15 @@ static void _solicit_servers(event_t *event)
msg_len += _compose_elapsed_time_opt(time);
msg_len += _compose_oro_opt((dhcpv6_opt_oro_t *)&send_buf[msg_len], oro_opts,
ARRAY_SIZE(oro_opts));
if (IS_USED(MODULE_GNRC_DHCPV6_CLIENT_MUD_URL)) {
const char mud_url[] = CONFIG_DHCPV6_CLIENT_MUD_URL;
assert(strlen(mud_url) <= MAX_MUD_URL_LENGTH);
assert(strncmp(mud_url, "https://", 8) == 0);
msg_len += _compose_mud_url_opt((dhcpv6_opt_mud_url_t *)&send_buf[msg_len],
mud_url, sizeof(send_buf) - msg_len);
}
msg_len += _add_ia_pd_from_config(&send_buf[msg_len]);
DEBUG("DHCPv6 client: send SOLICIT\n");
_flush_stale_replies(&sock);