1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-02-09 09:57:26 +03:00

Merge pull request #22943 from yuwata/dhcp6-client-requet-options

sd-dhcp6-client: requet options
This commit is contained in:
Yu Watanabe 2022-04-04 22:55:02 +09:00 committed by GitHub
commit f3e5c781f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 136 additions and 71 deletions

View File

@ -64,7 +64,7 @@ struct sd_dhcp6_client {
struct duid duid;
size_t duid_len;
be16_t *req_opts;
size_t req_opts_len;
size_t n_req_opts;
char *fqdn;
char *mudurl;
char **user_class;

View File

@ -51,18 +51,20 @@ bool dhcp6_option_can_request(uint16_t option) {
return false;
case SD_DHCP6_OPTION_SIP_SERVER_DOMAIN_NAME:
case SD_DHCP6_OPTION_SIP_SERVER_ADDRESS:
case SD_DHCP6_OPTION_DNS_SERVERS:
case SD_DHCP6_OPTION_DOMAIN_LIST:
case SD_DHCP6_OPTION_DNS_SERVER:
case SD_DHCP6_OPTION_DOMAIN:
return true;
case SD_DHCP6_OPTION_IA_PD:
case SD_DHCP6_OPTION_IA_PD_PREFIX:
return false;
case SD_DHCP6_OPTION_NIS_SERVERS:
case SD_DHCP6_OPTION_NISP_SERVERS:
case SD_DHCP6_OPTION_NIS_SERVER:
case SD_DHCP6_OPTION_NISP_SERVER:
case SD_DHCP6_OPTION_NIS_DOMAIN_NAME:
case SD_DHCP6_OPTION_NISP_DOMAIN_NAME:
case SD_DHCP6_OPTION_SNTP_SERVERS:
case SD_DHCP6_OPTION_SNTP_SERVER:
return true;
case SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME:
return false; /* This is automatically set when sending INFORMATION_REQUEST message. */
case SD_DHCP6_OPTION_BCMCS_SERVER_D:
case SD_DHCP6_OPTION_BCMCS_SERVER_A:
case SD_DHCP6_OPTION_GEOCONF_CIVIC:
@ -124,9 +126,9 @@ bool dhcp6_option_can_request(uint16_t option) {
case SD_DHCP6_OPTION_CLIENT_LINKLAYER_ADDR:
case SD_DHCP6_OPTION_LINK_ADDRESS:
case SD_DHCP6_OPTION_RADIUS:
case SD_DHCP6_OPTION_SOL_MAX_RT: /* Automatically set when sending SOLICIT message. */
case SD_DHCP6_OPTION_INF_MAX_RT: /* Automatically set when sending INFORMATION_REQUEST message. */
return false;
case SD_DHCP6_OPTION_SOL_MAX_RT:
case SD_DHCP6_OPTION_INF_MAX_RT:
case SD_DHCP6_OPTION_ADDRSEL:
case SD_DHCP6_OPTION_ADDRSEL_TABLE:
case SD_DHCP6_OPTION_V6_PCP_SERVER:

View File

@ -23,16 +23,10 @@
#include "io-util.h"
#include "random-util.h"
#include "socket-util.h"
#include "sort-util.h"
#include "strv.h"
#include "web-util.h"
static const uint16_t default_req_opts[] = {
SD_DHCP6_OPTION_DNS_SERVERS,
SD_DHCP6_OPTION_DOMAIN_LIST,
SD_DHCP6_OPTION_NTP_SERVER,
SD_DHCP6_OPTION_SNTP_SERVERS,
};
#define DHCP6_CLIENT_DONT_DESTROY(client) \
_cleanup_(sd_dhcp6_client_unrefp) _unused_ sd_dhcp6_client *_dont_destroy_##client = sd_dhcp6_client_ref(client)
@ -371,8 +365,12 @@ int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, int *enable
return 0;
}
static int be16_compare_func(const be16_t *a, const be16_t *b) {
return CMP(be16toh(*a), be16toh(*b));
}
int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) {
size_t t;
be16_t opt;
assert_return(client, -EINVAL);
assert_return(!sd_dhcp6_client_is_running(client), -EBUSY);
@ -380,15 +378,17 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option)
if (!dhcp6_option_can_request(option))
return -EINVAL;
for (t = 0; t < client->req_opts_len; t++)
if (client->req_opts[t] == htobe16(option))
return -EEXIST;
opt = htobe16(option);
if (typesafe_bsearch(&opt, client->req_opts, client->n_req_opts, be16_compare_func))
return -EEXIST;
if (!GREEDY_REALLOC(client->req_opts, client->req_opts_len + 1))
if (!GREEDY_REALLOC(client->req_opts, client->n_req_opts + 1))
return -ENOMEM;
client->req_opts[client->req_opts_len++] = htobe16(option);
client->req_opts[client->n_req_opts++] = opt;
/* Sort immediately to make the above binary search will work for the next time. */
typesafe_qsort(client->req_opts, client->n_req_opts, be16_compare_func);
return 0;
}
@ -635,6 +635,51 @@ static DHCP6MessageType client_message_type_from_state(sd_dhcp6_client *client)
}
}
static int client_append_oro(sd_dhcp6_client *client, uint8_t **opt, size_t *optlen) {
_cleanup_free_ be16_t *buf = NULL;
be16_t *req_opts;
size_t n;
assert(client);
assert(opt);
assert(optlen);
switch (client->state) {
case DHCP6_STATE_INFORMATION_REQUEST:
n = client->n_req_opts;
buf = new(be16_t, n + 2);
if (!buf)
return -ENOMEM;
memcpy_safe(buf, client->req_opts, n * sizeof(be16_t));
buf[n++] = htobe16(SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME); /* RFC 8415 section 21.23 */
buf[n++] = htobe16(SD_DHCP6_OPTION_INF_MAX_RT); /* RFC 8415 section 21.25 */
typesafe_qsort(buf, n, be16_compare_func);
req_opts = buf;
break;
case DHCP6_STATE_SOLICITATION:
n = client->n_req_opts;
buf = new(be16_t, n + 1);
if (!buf)
return -ENOMEM;
memcpy_safe(buf, client->req_opts, n * sizeof(be16_t));
buf[n++] = htobe16(SD_DHCP6_OPTION_SOL_MAX_RT); /* RFC 8415 section 21.24 */
typesafe_qsort(buf, n, be16_compare_func);
req_opts = buf;
break;
default:
n = client->n_req_opts;
req_opts = client->req_opts;
}
return dhcp6_option_append(opt, optlen, SD_DHCP6_OPTION_ORO, n * sizeof(be16_t), req_opts);
}
int dhcp6_client_send_message(sd_dhcp6_client *client) {
_cleanup_free_ DHCP6Message *message = NULL;
struct in6_addr all_servers =
@ -712,9 +757,7 @@ int dhcp6_client_send_message(sd_dhcp6_client *client) {
return r;
}
r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ORO,
client->req_opts_len * sizeof(be16_t),
client->req_opts);
r = client_append_oro(client, &opt, &optlen);
if (r < 0)
return r;
@ -1413,18 +1456,9 @@ DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_client, sd_dhcp6_client, dhcp6_client_fre
int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
_cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
_cleanup_free_ be16_t *req_opts = NULL;
size_t t;
assert_return(ret, -EINVAL);
req_opts = new(be16_t, ELEMENTSOF(default_req_opts));
if (!req_opts)
return -ENOMEM;
for (t = 0; t < ELEMENTSOF(default_req_opts); t++)
req_opts[t] = htobe16(default_req_opts[t]);
client = new(sd_dhcp6_client, 1);
if (!client)
return -ENOMEM;
@ -1436,8 +1470,6 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
.ifindex = -1,
.request_ia = DHCP6_REQUEST_IA_NA | DHCP6_REQUEST_IA_PD,
.fd = -1,
.req_opts_len = ELEMENTSOF(default_req_opts),
.req_opts = TAKE_PTR(req_opts),
};
*ret = TAKE_PTR(client);

View File

@ -570,14 +570,14 @@ static int dhcp6_lease_parse_message(
break;
case SD_DHCP6_OPTION_DNS_SERVERS:
case SD_DHCP6_OPTION_DNS_SERVER:
r = dhcp6_lease_add_dns(lease, optval, optlen);
if (r < 0)
log_dhcp6_client_errno(client, r, "Failed to parse DNS server option, ignoring: %m");
break;
case SD_DHCP6_OPTION_DOMAIN_LIST:
case SD_DHCP6_OPTION_DOMAIN:
r = dhcp6_lease_add_domains(lease, optval, optlen);
if (r < 0)
log_dhcp6_client_errno(client, r, "Failed to parse domain list option, ignoring: %m");
@ -591,7 +591,7 @@ static int dhcp6_lease_parse_message(
break;
case SD_DHCP6_OPTION_SNTP_SERVERS:
case SD_DHCP6_OPTION_SNTP_SERVER:
r = dhcp6_lease_add_sntp(lease, optval, optlen);
if (r < 0)
log_dhcp6_client_errno(client, r, "Failed to parse SNTP server option, ignoring: %m");

View File

@ -97,15 +97,15 @@ TEST(client_basic) {
assert_se(sd_dhcp6_client_set_fqdn(client, "~host.domain") == -EINVAL);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_CLIENTID) == -EINVAL);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVERS) == -EEXIST);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NTP_SERVER) == -EEXIST);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_SNTP_SERVERS) == -EEXIST);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DOMAIN_LIST) == -EEXIST);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVER) >= 0);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NTP_SERVER) >= 0);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_SNTP_SERVER) >= 0);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DOMAIN) >= 0);
assert_se(sd_dhcp6_client_set_request_option(client, 10) == -EINVAL);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NIS_SERVERS) == 0);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NISP_SERVERS) == 0);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NIS_SERVERS) == -EEXIST);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NISP_SERVERS) == -EEXIST);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NIS_SERVER) >= 0);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NISP_SERVER) >= 0);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NIS_SERVER) == -EEXIST);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NISP_SERVER) == -EEXIST);
assert_se(sd_dhcp6_client_set_information_request(client, 1) >= 0);
v = 0;
@ -403,7 +403,7 @@ TEST(client_parse_message_issue_22099) {
0x00, SD_DHCP6_OPTION_PREFERENCE, 0x00, 0x01,
0x00,
/* DNS servers */
0x00, SD_DHCP6_OPTION_DNS_SERVERS, 0x00, 0x10,
0x00, SD_DHCP6_OPTION_DNS_SERVER, 0x00, 0x10,
0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x15, 0xc8, 0xff, 0xfe, 0xef, 0x1e, 0x4e,
/* v6 pcp server */
0x00, SD_DHCP6_OPTION_V6_PCP_SERVER, 0x00, 0x10,
@ -450,11 +450,13 @@ static const uint8_t msg_information_request[] = {
0x0f, 0xb4, 0xe5,
/* MUD URL */
/* ORO */
0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x08,
0x00, SD_DHCP6_OPTION_DNS_SERVERS,
0x00, SD_DHCP6_OPTION_DOMAIN_LIST,
0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x0c,
0x00, SD_DHCP6_OPTION_DNS_SERVER,
0x00, SD_DHCP6_OPTION_DOMAIN,
0x00, SD_DHCP6_OPTION_SNTP_SERVER,
0x00, SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME,
0x00, SD_DHCP6_OPTION_NTP_SERVER,
0x00, SD_DHCP6_OPTION_SNTP_SERVERS,
0x00, SD_DHCP6_OPTION_INF_MAX_RT,
/* Client ID */
0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
CLIENT_ID_BYTES,
@ -490,11 +492,12 @@ static const uint8_t msg_solicit[] = {
/* Vendor Options */
/* MUD URL */
/* ORO */
0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x08,
0x00, SD_DHCP6_OPTION_DNS_SERVERS,
0x00, SD_DHCP6_OPTION_DOMAIN_LIST,
0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x0a,
0x00, SD_DHCP6_OPTION_DNS_SERVER,
0x00, SD_DHCP6_OPTION_DOMAIN,
0x00, SD_DHCP6_OPTION_SNTP_SERVER,
0x00, SD_DHCP6_OPTION_NTP_SERVER,
0x00, SD_DHCP6_OPTION_SNTP_SERVERS,
0x00, SD_DHCP6_OPTION_SOL_MAX_RT,
/* Client ID */
0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
CLIENT_ID_BYTES,
@ -554,10 +557,10 @@ static const uint8_t msg_request[] = {
/* MUD URL */
/* ORO */
0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x08,
0x00, SD_DHCP6_OPTION_DNS_SERVERS,
0x00, SD_DHCP6_OPTION_DOMAIN_LIST,
0x00, SD_DHCP6_OPTION_DNS_SERVER,
0x00, SD_DHCP6_OPTION_DOMAIN,
0x00, SD_DHCP6_OPTION_SNTP_SERVER,
0x00, SD_DHCP6_OPTION_NTP_SERVER,
0x00, SD_DHCP6_OPTION_SNTP_SERVERS,
/* Client ID */
0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
CLIENT_ID_BYTES,
@ -619,11 +622,11 @@ static const uint8_t msg_reply[] = {
0x40, /* prefixlen */
IA_PD_PREFIX1_BYTES,
/* DNS servers */
0x00, SD_DHCP6_OPTION_DNS_SERVERS, 0x00, 0x20,
0x00, SD_DHCP6_OPTION_DNS_SERVER, 0x00, 0x20,
DNS1_BYTES,
DNS2_BYTES,
/* SNTP servers */
0x00, SD_DHCP6_OPTION_SNTP_SERVERS, 0x00, 0x20,
0x00, SD_DHCP6_OPTION_SNTP_SERVER, 0x00, 0x20,
SNTP1_BYTES,
SNTP2_BYTES,
/* NTP servers */
@ -638,7 +641,7 @@ static const uint8_t msg_reply[] = {
0x00, DHCP6_NTP_SUBOPTION_SRV_FQDN, 0x00, 0x0b,
0x03, 'n', 't', 'p', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
/* Domain list */
0x00, SD_DHCP6_OPTION_DOMAIN_LIST, 0x00, 0x0b,
0x00, SD_DHCP6_OPTION_DOMAIN, 0x00, 0x0b,
0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
/* Client FQDN */
0x00, SD_DHCP6_OPTION_CLIENT_FQDN, 0x00, 0x12,
@ -698,11 +701,11 @@ static const uint8_t msg_advertise[] = {
0x40, /* prefixlen */
IA_PD_PREFIX1_BYTES,
/* DNS servers */
0x00, SD_DHCP6_OPTION_DNS_SERVERS, 0x00, 0x20,
0x00, SD_DHCP6_OPTION_DNS_SERVER, 0x00, 0x20,
DNS1_BYTES,
DNS2_BYTES,
/* SNTP servers */
0x00, SD_DHCP6_OPTION_SNTP_SERVERS, 0x00, 0x20,
0x00, SD_DHCP6_OPTION_SNTP_SERVER, 0x00, 0x20,
SNTP1_BYTES,
SNTP2_BYTES,
/* NTP servers */
@ -717,7 +720,7 @@ static const uint8_t msg_advertise[] = {
0x00, DHCP6_NTP_SUBOPTION_SRV_FQDN, 0x00, 0x0b,
0x03, 'n', 't', 'p', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
/* Domain list */
0x00, SD_DHCP6_OPTION_DOMAIN_LIST, 0x00, 0x0b,
0x00, SD_DHCP6_OPTION_DOMAIN, 0x00, 0x0b,
0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
/* Client FQDN */
0x00, SD_DHCP6_OPTION_CLIENT_FQDN, 0x00, 0x12,
@ -977,6 +980,11 @@ TEST(dhcp6_client) {
assert_se(sd_dhcp6_client_set_iaid(client, unaligned_read_be32((uint8_t[]) { IA_ID_BYTES })) >= 0);
dhcp6_client_set_test_mode(client, true);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVER) >= 0);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DOMAIN) >= 0);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NTP_SERVER) >= 0);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_SNTP_SERVER) >= 0);
assert_se(sd_dhcp6_client_set_information_request(client, true) >= 0);
assert_se(sd_dhcp6_client_set_callback(client, test_client_callback, NULL) >= 0);

View File

@ -622,6 +622,29 @@ static int dhcp6_configure(Link *link) {
return log_link_debug_errno(link, r, "DHCPv6 CLIENT: Failed to set MUD URL: %m");
}
if (link->network->dhcp6_use_dns) {
r = sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVER);
if (r < 0)
return log_link_debug_errno(link, r, "DHCPv6 CLIENT: Failed to request DNS servers: %m");
}
if (link->network->dhcp6_use_domains > 0) {
r = sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DOMAIN);
if (r < 0)
return log_link_debug_errno(link, r, "DHCPv6 CLIENT: Failed to request domains: %m");
}
if (link->network->dhcp6_use_ntp) {
r = sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NTP_SERVER);
if (r < 0)
return log_link_debug_errno(link, r, "DHCPv6 CLIENT: Failed to request NTP servers: %m");
/* If the server does not provide NTP servers, then we fallback to use SNTP servers. */
r = sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_SNTP_SERVER);
if (r < 0)
return log_link_debug_errno(link, r, "DHCPv6 CLIENT: Failed to request SNTP servers: %m");
}
SET_FOREACH(request_options, link->network->dhcp6_request_options) {
uint32_t option = PTR_TO_UINT32(request_options);

View File

@ -134,7 +134,7 @@ enum {
SD_DHCP_OPTION_NDS_SERVER = 85, /* [RFC2241] */
SD_DHCP_OPTION_NDS_TREE_NAME = 86, /* [RFC2241] */
SD_DHCP_OPTION_NDS_CONTEXT = 87, /* [RFC2241] */
SD_DHCP_OPTION_BCMCS_CONTROLLER_DOMAIN_NAM = 88, /* [RFC4280] */
SD_DHCP_OPTION_BCMCS_CONTROLLER_DOMAIN_NAME = 88, /* [RFC4280] */
SD_DHCP_OPTION_BCMCS_CONTROLLER_ADDRESS = 89, /* [RFC4280] */
SD_DHCP_OPTION_AUTHENTICATION = 90, /* [RFC3118] */
SD_DHCP_OPTION_CLIENT_LAST_TRANSACTION_TIME = 91, /* [RFC4388] */
@ -173,7 +173,7 @@ enum {
SD_DHCP_OPTION_CAPWAP_AC_ADDRESS = 138, /* [RFC5417] */
SD_DHCP_OPTION_MOS_ADDRESS = 139, /* [RFC5678] */
SD_DHCP_OPTION_MOS_FQDN = 140, /* [RFC5678] */
SD_DHCP_OPTION_SIP_SERVICE_DOMAINS = 141, /* [RFC6011] */
SD_DHCP_OPTION_SIP_SERVICE_DOMAIN = 141, /* [RFC6011] */
SD_DHCP_OPTION_ANDSF_ADDRESS = 142, /* [RFC6153] */
SD_DHCP_OPTION_SZTP_REDIRECT = 143, /* [RFC8572] */
SD_DHCP_OPTION_GEOLOC = 144, /* [RFC6225] */

View File

@ -63,15 +63,15 @@ enum {
SD_DHCP6_OPTION_RECONF_ACCEPT = 20, /* RFC 8415 */
SD_DHCP6_OPTION_SIP_SERVER_DOMAIN_NAME = 21, /* RFC 3319 */
SD_DHCP6_OPTION_SIP_SERVER_ADDRESS = 22, /* RFC 3319 */
SD_DHCP6_OPTION_DNS_SERVERS = 23, /* RFC 3646 */
SD_DHCP6_OPTION_DOMAIN_LIST = 24, /* RFC 3646 */
SD_DHCP6_OPTION_DNS_SERVER = 23, /* RFC 3646 */
SD_DHCP6_OPTION_DOMAIN = 24, /* RFC 3646 */
SD_DHCP6_OPTION_IA_PD = 25, /* RFC 3633, RFC 8415 */
SD_DHCP6_OPTION_IA_PD_PREFIX = 26, /* RFC 3633, RFC 8415 */
SD_DHCP6_OPTION_NIS_SERVERS = 27, /* RFC 3898 */
SD_DHCP6_OPTION_NISP_SERVERS = 28, /* RFC 3898 */
SD_DHCP6_OPTION_NIS_SERVER = 27, /* RFC 3898 */
SD_DHCP6_OPTION_NISP_SERVER = 28, /* RFC 3898 */
SD_DHCP6_OPTION_NIS_DOMAIN_NAME = 29, /* RFC 3898 */
SD_DHCP6_OPTION_NISP_DOMAIN_NAME = 30, /* RFC 3898 */
SD_DHCP6_OPTION_SNTP_SERVERS = 31, /* RFC 4075, deprecated */
SD_DHCP6_OPTION_SNTP_SERVER = 31, /* RFC 4075, deprecated */
SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME = 32, /* RFC 4242, 8415, sec. 21.23 */
SD_DHCP6_OPTION_BCMCS_SERVER_D = 33, /* RFC 4280 */
SD_DHCP6_OPTION_BCMCS_SERVER_A = 34, /* RFC 4280 */