use super::constants::{
DHCPV6_OPTION_AFTR_NAME, DHCPV6_OPTION_DHCP4_O_DHCP6_SERVER,
DHCPV6_OPTION_ERP_LOCAL_DOMAIN_NAME, DHCPV6_OPTION_IAADDR, DHCPV6_OPTION_IAPREFIX,
DHCPV6_OPTION_PD_EXCLUDE, DHCPV6_OPTION_S46_CONT_LW, DHCPV6_OPTION_S46_CONT_MAPE,
DHCPV6_OPTION_S46_CONT_MAPT, DHCPV6_OPTION_STATUS_CODE, DHCPV6_OPTION_V6_DNR,
DHCPV6_RADIUS_ATTRIBUTE_DELEGATED_IPV6_PREFIX,
DHCPV6_RADIUS_ATTRIBUTE_DELEGATED_IPV6_PREFIX_POOL,
DHCPV6_RADIUS_ATTRIBUTE_DHCPV6_OPTIONS_EXTENDED_TYPE,
DHCPV6_RADIUS_ATTRIBUTE_DNS_SERVER_IPV6_ADDRESS, DHCPV6_RADIUS_ATTRIBUTE_DS_LITE_TUNNEL_NAME,
DHCPV6_RADIUS_ATTRIBUTE_EXTENDED_TYPE_1, DHCPV6_RADIUS_ATTRIBUTE_FRAMED_IPV6_ADDRESS,
DHCPV6_RADIUS_ATTRIBUTE_STATEFUL_IPV6_ADDRESS_POOL, DHCPV6_RADIUS_ATTRIBUTE_VENDOR_SPECIFIC,
DHCPV6_SUPPORTED_TRANSPORT_DOMTLS_BIT, DHCPV6_SUPPORTED_TRANSPORT_MAX_BIT,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Dhcpv6OptionStatus {
Reserved,
Assigned,
Obsolete,
Unassigned,
Unknown,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Dhcpv6ClientOro {
No,
Yes,
Optional,
RequiredForInformationRequest,
RequiredForSolicit,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Dhcpv6OptionSingleton {
Yes,
No,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Dhcpv6RsooOptionPermission {
Permitted,
NotPermitted,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Dhcpv6S46PriorityOptionPermission {
Permitted,
NotPermitted,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Dhcpv6AuxiliaryRegistryStatus {
Assigned,
Unassigned,
Unknown,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Dhcpv6RadiusAttributeCode {
type_code: u8,
extended_type: Option<u8>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Dhcpv6RadiusAttributeMeta {
pub code: Dhcpv6RadiusAttributeCode,
pub name: &'static str,
pub status: Dhcpv6AuxiliaryRegistryStatus,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Dhcpv6SupportedTransportMeta {
pub bit_position: u8,
pub description: &'static str,
pub mnemonic: Option<&'static str>,
pub status: Dhcpv6AuxiliaryRegistryStatus,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Dhcpv6RadiusDhcpv6OptionPermission {
Permitted,
NotPermitted,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Dhcpv6OptionPlacementStatus {
Known,
Questionable,
Unknown,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Dhcpv6OptionPlacementReport {
pub code: u16,
pub registry_status: Dhcpv6OptionStatus,
pub top_level: Dhcpv6OptionPlacementStatus,
pub ia_na: Dhcpv6OptionPlacementStatus,
pub ia_pd: Dhcpv6OptionPlacementStatus,
pub relay_supplied: Dhcpv6OptionPlacementStatus,
pub oro_eligible: Dhcpv6OptionPlacementStatus,
}
impl Dhcpv6OptionSingleton {
pub const fn is_singleton(self) -> bool {
matches!(self, Self::Yes)
}
}
impl Dhcpv6OptionPlacementStatus {
pub const fn is_known(self) -> bool {
matches!(self, Self::Known)
}
pub const fn is_questionable(self) -> bool {
matches!(self, Self::Questionable)
}
pub const fn is_unknown(self) -> bool {
matches!(self, Self::Unknown)
}
}
impl Dhcpv6AuxiliaryRegistryStatus {
pub const fn is_assigned(self) -> bool {
matches!(self, Self::Assigned)
}
}
impl Dhcpv6RadiusAttributeCode {
pub const fn standard(type_code: u8) -> Self {
Self {
type_code,
extended_type: None,
}
}
pub const fn extended(type_code: u8, extended_type: u8) -> Self {
Self {
type_code,
extended_type: Some(extended_type),
}
}
pub const fn type_code(self) -> u8 {
self.type_code
}
pub const fn extended_type(self) -> Option<u8> {
self.extended_type
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Dhcpv6OptionMeta {
pub code: u16,
pub name: &'static str,
pub status: Dhcpv6OptionStatus,
pub client_oro: Option<Dhcpv6ClientOro>,
pub singleton: Option<Dhcpv6OptionSingleton>,
}
pub const DHCPV6_OPTION_REGISTRY_EXPLICIT_END: u16 = 150;
pub const DHCPV6_OPTION_UNASSIGNED_START: u16 = 151;
pub const DHCPV6_OPTION_UNASSIGNED_END: u16 = u16::MAX;
pub const fn dhcpv6_option_meta(code: u16) -> Dhcpv6OptionMeta {
if code <= DHCPV6_OPTION_REGISTRY_EXPLICIT_END {
return DHCPV6_OPTION_META[code as usize];
}
if code >= DHCPV6_OPTION_UNASSIGNED_START {
return entry(code, "Unassigned", UNASSIGNED, None, None);
}
entry(code, "Unknown", UNKNOWN, None, None)
}
pub const fn dhcpv6_option_status(code: u16) -> Dhcpv6OptionStatus {
dhcpv6_option_meta(code).status
}
pub const fn dhcpv6_option_registered(code: u16) -> bool {
matches!(
dhcpv6_option_status(code),
Dhcpv6OptionStatus::Assigned | Dhcpv6OptionStatus::Obsolete
)
}
pub const fn dhcpv6_option_name(code: u16) -> Option<&'static str> {
match dhcpv6_option_meta(code).status {
Dhcpv6OptionStatus::Assigned | Dhcpv6OptionStatus::Obsolete => {
Some(dhcpv6_option_meta(code).name)
}
Dhcpv6OptionStatus::Reserved
| Dhcpv6OptionStatus::Unassigned
| Dhcpv6OptionStatus::Unknown => None,
}
}
pub const fn dhcpv6_option_placement_report(code: u16) -> Dhcpv6OptionPlacementReport {
Dhcpv6OptionPlacementReport {
code,
registry_status: dhcpv6_option_status(code),
top_level: dhcpv6_option_top_level_placement(code),
ia_na: dhcpv6_option_ia_na_placement(code),
ia_pd: dhcpv6_option_ia_pd_placement(code),
relay_supplied: dhcpv6_option_relay_supplied_placement(code),
oro_eligible: dhcpv6_option_oro_placement(code),
}
}
pub const fn dhcpv6_option_top_level_placement(code: u16) -> Dhcpv6OptionPlacementStatus {
if dhcpv6_option_nested_only(code) {
Dhcpv6OptionPlacementStatus::Questionable
} else if dhcpv6_option_registered(code) {
Dhcpv6OptionPlacementStatus::Known
} else {
Dhcpv6OptionPlacementStatus::Unknown
}
}
pub const fn dhcpv6_option_ia_na_placement(code: u16) -> Dhcpv6OptionPlacementStatus {
placement_from_known(code, dhcpv6_option_known_ia_na_nested(code))
}
pub const fn dhcpv6_option_ia_pd_placement(code: u16) -> Dhcpv6OptionPlacementStatus {
placement_from_known(code, dhcpv6_option_known_ia_pd_nested(code))
}
pub const fn dhcpv6_option_relay_supplied_placement(code: u16) -> Dhcpv6OptionPlacementStatus {
placement_from_known(code, dhcpv6_rsoo_option_permitted(code))
}
pub const fn dhcpv6_option_oro_placement(code: u16) -> Dhcpv6OptionPlacementStatus {
match dhcpv6_option_meta(code).client_oro {
Some(
Dhcpv6ClientOro::Yes
| Dhcpv6ClientOro::Optional
| Dhcpv6ClientOro::RequiredForInformationRequest
| Dhcpv6ClientOro::RequiredForSolicit,
) => Dhcpv6OptionPlacementStatus::Known,
Some(Dhcpv6ClientOro::No) => Dhcpv6OptionPlacementStatus::Questionable,
None => Dhcpv6OptionPlacementStatus::Unknown,
}
}
pub const fn dhcpv6_rsoo_option_permission(code: u16) -> Dhcpv6RsooOptionPermission {
match code {
DHCPV6_OPTION_ERP_LOCAL_DOMAIN_NAME => Dhcpv6RsooOptionPermission::Permitted,
_ => Dhcpv6RsooOptionPermission::NotPermitted,
}
}
pub const fn dhcpv6_rsoo_option_permitted(code: u16) -> bool {
matches!(
dhcpv6_rsoo_option_permission(code),
Dhcpv6RsooOptionPermission::Permitted
)
}
pub const fn dhcpv6_s46_priority_option_permission(code: u16) -> Dhcpv6S46PriorityOptionPermission {
match code {
DHCPV6_OPTION_AFTR_NAME
| DHCPV6_OPTION_DHCP4_O_DHCP6_SERVER
| DHCPV6_OPTION_S46_CONT_MAPE
| DHCPV6_OPTION_S46_CONT_MAPT
| DHCPV6_OPTION_S46_CONT_LW => Dhcpv6S46PriorityOptionPermission::Permitted,
_ => Dhcpv6S46PriorityOptionPermission::NotPermitted,
}
}
pub const fn dhcpv6_s46_priority_option_permitted(code: u16) -> bool {
matches!(
dhcpv6_s46_priority_option_permission(code),
Dhcpv6S46PriorityOptionPermission::Permitted
)
}
pub const fn dhcpv6_radius_attribute_meta(
code: Dhcpv6RadiusAttributeCode,
) -> Dhcpv6RadiusAttributeMeta {
match (code.type_code, code.extended_type) {
(DHCPV6_RADIUS_ATTRIBUTE_VENDOR_SPECIFIC, None) => radius_attr(
code,
"Vendor-Specific",
Dhcpv6AuxiliaryRegistryStatus::Assigned,
),
(DHCPV6_RADIUS_ATTRIBUTE_DELEGATED_IPV6_PREFIX, None) => radius_attr(
code,
"Delegated-IPv6-Prefix",
Dhcpv6AuxiliaryRegistryStatus::Assigned,
),
(DHCPV6_RADIUS_ATTRIBUTE_DS_LITE_TUNNEL_NAME, None) => radius_attr(
code,
"DS-Lite-Tunnel-Name",
Dhcpv6AuxiliaryRegistryStatus::Assigned,
),
(DHCPV6_RADIUS_ATTRIBUTE_FRAMED_IPV6_ADDRESS, None) => radius_attr(
code,
"Framed-IPv6-Address",
Dhcpv6AuxiliaryRegistryStatus::Assigned,
),
(DHCPV6_RADIUS_ATTRIBUTE_DNS_SERVER_IPV6_ADDRESS, None) => radius_attr(
code,
"DNS-Server-IPv6-Address",
Dhcpv6AuxiliaryRegistryStatus::Assigned,
),
(DHCPV6_RADIUS_ATTRIBUTE_DELEGATED_IPV6_PREFIX_POOL, None) => radius_attr(
code,
"Delegated-IPv6-Prefix-Pool",
Dhcpv6AuxiliaryRegistryStatus::Assigned,
),
(DHCPV6_RADIUS_ATTRIBUTE_STATEFUL_IPV6_ADDRESS_POOL, None) => radius_attr(
code,
"Stateful-IPv6-Address-Pool",
Dhcpv6AuxiliaryRegistryStatus::Assigned,
),
(
DHCPV6_RADIUS_ATTRIBUTE_EXTENDED_TYPE_1,
Some(DHCPV6_RADIUS_ATTRIBUTE_DHCPV6_OPTIONS_EXTENDED_TYPE),
) => radius_attr(
code,
"DHCPv6-Options",
Dhcpv6AuxiliaryRegistryStatus::Assigned,
),
_ => radius_attr(
code,
"Unassigned",
Dhcpv6AuxiliaryRegistryStatus::Unassigned,
),
}
}
pub const fn dhcpv6_radius_attribute_name(code: Dhcpv6RadiusAttributeCode) -> Option<&'static str> {
match dhcpv6_radius_attribute_meta(code).status {
Dhcpv6AuxiliaryRegistryStatus::Assigned => Some(dhcpv6_radius_attribute_meta(code).name),
Dhcpv6AuxiliaryRegistryStatus::Unassigned | Dhcpv6AuxiliaryRegistryStatus::Unknown => None,
}
}
pub const fn dhcpv6_radius_attribute_permitted(code: Dhcpv6RadiusAttributeCode) -> bool {
dhcpv6_radius_attribute_meta(code).status.is_assigned()
}
pub const fn dhcpv6_supported_transport_meta(bit_position: u8) -> Dhcpv6SupportedTransportMeta {
match bit_position {
DHCPV6_SUPPORTED_TRANSPORT_DOMTLS_BIT => Dhcpv6SupportedTransportMeta {
bit_position,
description: "DNS over mutually authenticated TLS",
mnemonic: Some("DomTLS"),
status: Dhcpv6AuxiliaryRegistryStatus::Assigned,
},
1..=DHCPV6_SUPPORTED_TRANSPORT_MAX_BIT => Dhcpv6SupportedTransportMeta {
bit_position,
description: "Unassigned",
mnemonic: None,
status: Dhcpv6AuxiliaryRegistryStatus::Unassigned,
},
_ => Dhcpv6SupportedTransportMeta {
bit_position,
description: "Unknown",
mnemonic: None,
status: Dhcpv6AuxiliaryRegistryStatus::Unknown,
},
}
}
pub const fn dhcpv6_supported_transport_name(bit_position: u8) -> Option<&'static str> {
dhcpv6_supported_transport_meta(bit_position).mnemonic
}
pub const fn dhcpv6_radius_dhcpv6_option_permission(
code: u16,
) -> Dhcpv6RadiusDhcpv6OptionPermission {
match code {
DHCPV6_OPTION_V6_DNR => Dhcpv6RadiusDhcpv6OptionPermission::Permitted,
_ => Dhcpv6RadiusDhcpv6OptionPermission::NotPermitted,
}
}
pub const fn dhcpv6_radius_dhcpv6_option_permitted(code: u16) -> bool {
matches!(
dhcpv6_radius_dhcpv6_option_permission(code),
Dhcpv6RadiusDhcpv6OptionPermission::Permitted
)
}
const fn radius_attr(
code: Dhcpv6RadiusAttributeCode,
name: &'static str,
status: Dhcpv6AuxiliaryRegistryStatus,
) -> Dhcpv6RadiusAttributeMeta {
Dhcpv6RadiusAttributeMeta { code, name, status }
}
const fn placement_from_known(code: u16, known: bool) -> Dhcpv6OptionPlacementStatus {
if known {
Dhcpv6OptionPlacementStatus::Known
} else if dhcpv6_option_registered(code) {
Dhcpv6OptionPlacementStatus::Questionable
} else {
Dhcpv6OptionPlacementStatus::Unknown
}
}
const fn dhcpv6_option_nested_only(code: u16) -> bool {
matches!(
code,
DHCPV6_OPTION_IAADDR | DHCPV6_OPTION_IAPREFIX | DHCPV6_OPTION_PD_EXCLUDE
)
}
const fn dhcpv6_option_known_ia_na_nested(code: u16) -> bool {
matches!(code, DHCPV6_OPTION_IAADDR | DHCPV6_OPTION_STATUS_CODE)
}
const fn dhcpv6_option_known_ia_pd_nested(code: u16) -> bool {
matches!(code, DHCPV6_OPTION_IAPREFIX | DHCPV6_OPTION_STATUS_CODE)
}
const fn entry(
code: u16,
name: &'static str,
status: Dhcpv6OptionStatus,
client_oro: Option<Dhcpv6ClientOro>,
singleton: Option<Dhcpv6OptionSingleton>,
) -> Dhcpv6OptionMeta {
Dhcpv6OptionMeta {
code,
name,
status,
client_oro,
singleton,
}
}
type Oro = Dhcpv6ClientOro;
type Singleton = Dhcpv6OptionSingleton;
const RESERVED: Dhcpv6OptionStatus = Dhcpv6OptionStatus::Reserved;
const ASSIGNED: Dhcpv6OptionStatus = Dhcpv6OptionStatus::Assigned;
const OBSOLETE: Dhcpv6OptionStatus = Dhcpv6OptionStatus::Obsolete;
const UNASSIGNED: Dhcpv6OptionStatus = Dhcpv6OptionStatus::Unassigned;
const UNKNOWN: Dhcpv6OptionStatus = Dhcpv6OptionStatus::Unknown;
const DHCPV6_OPTION_META: [Dhcpv6OptionMeta; 151] = [
entry(0, "Reserved", RESERVED, None, None),
entry(
1,
"OPTION_CLIENTID",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
2,
"OPTION_SERVERID",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
3,
"OPTION_IA_NA",
ASSIGNED,
Some(Oro::No),
Some(Singleton::No),
),
entry(
4,
"OPTION_IA_TA",
OBSOLETE,
Some(Oro::No),
Some(Singleton::No),
),
entry(
5,
"OPTION_IAADDR",
ASSIGNED,
Some(Oro::No),
Some(Singleton::No),
),
entry(
6,
"OPTION_ORO",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
7,
"OPTION_PREFERENCE",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
8,
"OPTION_ELAPSED_TIME",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
9,
"OPTION_RELAY_MSG",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
10,
"Unassigned",
UNASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
11,
"OPTION_AUTH",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
12,
"OPTION_UNICAST",
OBSOLETE,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
13,
"OPTION_STATUS_CODE",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
14,
"OPTION_RAPID_COMMIT",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
15,
"OPTION_USER_CLASS",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
16,
"OPTION_VENDOR_CLASS",
ASSIGNED,
Some(Oro::No),
Some(Singleton::No),
),
entry(
17,
"OPTION_VENDOR_OPTS",
ASSIGNED,
Some(Oro::Optional),
Some(Singleton::No),
),
entry(
18,
"OPTION_INTERFACE_ID",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
19,
"OPTION_RECONF_MSG",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
20,
"OPTION_RECONF_ACCEPT",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
21,
"OPTION_SIP_SERVER_D",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
22,
"OPTION_SIP_SERVER_A",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
23,
"OPTION_DNS_SERVERS",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
24,
"OPTION_DOMAIN_LIST",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
25,
"OPTION_IA_PD",
ASSIGNED,
Some(Oro::No),
Some(Singleton::No),
),
entry(
26,
"OPTION_IAPREFIX",
ASSIGNED,
Some(Oro::No),
Some(Singleton::No),
),
entry(
27,
"OPTION_NIS_SERVERS",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
28,
"OPTION_NISP_SERVERS",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
29,
"OPTION_NIS_DOMAIN_NAME",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
30,
"OPTION_NISP_DOMAIN_NAME",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
31,
"OPTION_SNTP_SERVERS",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
32,
"OPTION_INFORMATION_REFRESH_TIME",
ASSIGNED,
Some(Oro::RequiredForInformationRequest),
Some(Singleton::Yes),
),
entry(
33,
"OPTION_BCMCS_SERVER_D",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
34,
"OPTION_BCMCS_SERVER_A",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
35,
"Unassigned",
UNASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
36,
"OPTION_GEOCONF_CIVIC",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
37,
"OPTION_REMOTE_ID",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
38,
"OPTION_SUBSCRIBER_ID",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
39,
"OPTION_CLIENT_FQDN",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
40,
"OPTION_PANA_AGENT",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
41,
"OPTION_NEW_POSIX_TIMEZONE",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
42,
"OPTION_NEW_TZDB_TIMEZONE",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
43,
"OPTION_ERO",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
44,
"OPTION_LQ_QUERY",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
45,
"OPTION_CLIENT_DATA",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
46,
"OPTION_CLT_TIME",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
47,
"OPTION_LQ_RELAY_DATA",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
48,
"OPTION_LQ_CLIENT_LINK",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
49,
"OPTION_MIP6_HNIDF",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
50,
"OPTION_MIP6_VDINF",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
51,
"OPTION_V6_LOST",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
52,
"OPTION_CAPWAP_AC_V6",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
53,
"OPTION_RELAY_ID",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
54,
"OPTION-IPv6_Address-MoS",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
55,
"OPTION-IPv6_FQDN-MoS",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
56,
"OPTION_NTP_SERVER",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
57,
"OPTION_V6_ACCESS_DOMAIN",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
58,
"OPTION_SIP_UA_CS_LIST",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
59,
"OPT_BOOTFILE_URL",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
60,
"OPT_BOOTFILE_PARAM",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
61,
"OPTION_CLIENT_ARCH_TYPE",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
62,
"OPTION_NII",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
63,
"OPTION_GEOLOCATION",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
64,
"OPTION_AFTR_NAME",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
65,
"OPTION_ERP_LOCAL_DOMAIN_NAME",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
66,
"OPTION_RSOO",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
67,
"OPTION_PD_EXCLUDE",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
68,
"OPTION_VSS",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
69,
"OPTION_MIP6_IDINF",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
70,
"OPTION_MIP6_UDINF",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
71,
"OPTION_MIP6_HNP",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
72,
"OPTION_MIP6_HAA",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
73,
"OPTION_MIP6_HAF",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
74,
"OPTION_RDNSS_SELECTION",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
75,
"OPTION_KRB_PRINCIPAL_NAME",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
76,
"OPTION_KRB_REALM_NAME",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
77,
"OPTION_KRB_DEFAULT_REALM_NAME",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
78,
"OPTION_KRB_KDC",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
79,
"OPTION_CLIENT_LINKLAYER_ADDR",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
80,
"OPTION_LINK_ADDRESS",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
81,
"OPTION_RADIUS",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
82,
"OPTION_SOL_MAX_RT",
ASSIGNED,
Some(Oro::RequiredForSolicit),
Some(Singleton::Yes),
),
entry(
83,
"OPTION_INF_MAX_RT",
ASSIGNED,
Some(Oro::RequiredForInformationRequest),
Some(Singleton::Yes),
),
entry(
84,
"OPTION_ADDRSEL",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
85,
"OPTION_ADDRSEL_TABLE",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
86,
"OPTION_V6_PCP_SERVER",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::No),
),
entry(
87,
"OPTION_DHCPV4_MSG",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
88,
"OPTION_DHCP4_O_DHCP6_SERVER",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
89,
"OPTION_S46_RULE",
ASSIGNED,
Some(Oro::No),
Some(Singleton::No),
),
entry(
90,
"OPTION_S46_BR",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::No),
),
entry(
91,
"OPTION_S46_DMR",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
92,
"OPTION_S46_V4V6BIND",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
93,
"OPTION_S46_PORTPARAMS",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
94,
"OPTION_S46_CONT_MAPE",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::No),
),
entry(
95,
"OPTION_S46_CONT_MAPT",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
96,
"OPTION_S46_CONT_LW",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
97,
"OPTION_4RD",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
98,
"OPTION_4RD_MAP_RULE",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
99,
"OPTION_4RD_NON_MAP_RULE",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
100,
"OPTION_LQ_BASE_TIME",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
101,
"OPTION_LQ_START_TIME",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
102,
"OPTION_LQ_END_TIME",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
103,
"DHCP Captive-Portal",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
104,
"OPTION_MPL_PARAMETERS",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::No),
),
entry(
105,
"OPTION_ANI_ATT",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
106,
"OPTION_ANI_NETWORK_NAME",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
107,
"OPTION_ANI_AP_NAME",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
108,
"OPTION_ANI_AP_BSSID",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
109,
"OPTION_ANI_OPERATOR_ID",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
110,
"OPTION_ANI_OPERATOR_REALM",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
111,
"OPTION_S46_PRIORITY",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
112,
"OPTION_MUD_URL_V6",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
113,
"OPTION_V6_PREFIX64",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::No),
),
entry(
114,
"OPTION_F_BINDING_STATUS",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
115,
"OPTION_F_CONNECT_FLAGS",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
116,
"OPTION_F_DNS_REMOVAL_INFO",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
117,
"OPTION_F_DNS_HOST_NAME",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
118,
"OPTION_F_DNS_ZONE_NAME",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
119,
"OPTION_F_DNS_FLAGS",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
120,
"OPTION_F_EXPIRATION_TIME",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
121,
"OPTION_F_MAX_UNACKED_BNDUPD",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
122,
"OPTION_F_MCLT",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
123,
"OPTION_F_PARTNER_LIFETIME",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
124,
"OPTION_F_PARTNER_LIFETIME_SENT",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
125,
"OPTION_F_PARTNER_DOWN_TIME",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
126,
"OPTION_F_PARTNER_RAW_CLT_TIME",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
127,
"OPTION_F_PROTOCOL_VERSION",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
128,
"OPTION_F_KEEPALIVE_TIME",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
129,
"OPTION_F_RECONFIGURE_DATA",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
130,
"OPTION_F_RELATIONSHIP_NAME",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
131,
"OPTION_F_SERVER_FLAGS",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
132,
"OPTION_F_SERVER_STATE",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
133,
"OPTION_F_START_TIME_OF_STATE",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
134,
"OPTION_F_STATE_EXPIRATION_TIME",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
135,
"OPTION_RELAY_PORT",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
136,
"OPTION_V6_SZTP_REDIRECT",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
137,
"OPTION_S46_BIND_IPV6_PREFIX",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
138,
"OPTION_IA_LL",
ASSIGNED,
Some(Oro::No),
Some(Singleton::No),
),
entry(
139,
"OPTION_LLADDR",
ASSIGNED,
Some(Oro::No),
Some(Singleton::No),
),
entry(
140,
"OPTION_SLAP_QUAD",
ASSIGNED,
Some(Oro::No),
Some(Singleton::Yes),
),
entry(
141,
"OPTION_V6_DOTS_RI",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
142,
"OPTION_V6_DOTS_ADDRESS",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
143,
"OPTION-IPv6_Address-ANDSF",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
144,
"OPTION_V6_DNR",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::No),
),
entry(
145,
"OPTION_REGISTERED_DOMAIN",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::No),
),
entry(
146,
"OPTION_FORWARD_DIST_MANAGER",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
147,
"OPTION_REVERSE_DIST_MANAGER",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
148,
"OPTION_ADDR_REG_ENABLE",
ASSIGNED,
Some(Oro::Yes),
Some(Singleton::Yes),
),
entry(
149,
"OPTION_IA_SRV6_LOCATOR",
ASSIGNED,
Some(Oro::No),
Some(Singleton::No),
),
entry(
150,
"OPTION_IALOCATOR",
ASSIGNED,
Some(Oro::No),
Some(Singleton::No),
),
];
#[cfg(test)]
mod dhcpv6_option_registry_tests {
use crate::protocols::dhcp::v6::constants::{
DHCPV6_OPTION_CLIENTID, DHCPV6_OPTION_DNS_SERVERS, DHCPV6_OPTION_ERP_LOCAL_DOMAIN_NAME,
DHCPV6_OPTION_IAADDR, DHCPV6_OPTION_IAPREFIX, DHCPV6_OPTION_RADIUS,
DHCPV6_OPTION_S46_CONT_MAPE, DHCPV6_OPTION_S46_RULE, DHCPV6_OPTION_STATUS_CODE,
DHCPV6_OPTION_V6_DNR, DHCPV6_RADIUS_ATTRIBUTE_DHCPV6_OPTIONS_EXTENDED_TYPE,
DHCPV6_RADIUS_ATTRIBUTE_EXTENDED_TYPE_1, DHCPV6_RADIUS_ATTRIBUTE_VENDOR_SPECIFIC,
DHCPV6_SUPPORTED_TRANSPORT_DOMTLS_BIT,
};
use super::{
dhcpv6_option_ia_na_placement, dhcpv6_option_meta, dhcpv6_option_name,
dhcpv6_option_oro_placement, dhcpv6_option_placement_report, dhcpv6_option_status,
dhcpv6_option_top_level_placement, dhcpv6_radius_attribute_meta,
dhcpv6_radius_attribute_name, dhcpv6_radius_attribute_permitted,
dhcpv6_radius_dhcpv6_option_permission, dhcpv6_radius_dhcpv6_option_permitted,
dhcpv6_rsoo_option_permission, dhcpv6_rsoo_option_permitted,
dhcpv6_s46_priority_option_permission, dhcpv6_s46_priority_option_permitted,
dhcpv6_supported_transport_meta, dhcpv6_supported_transport_name,
Dhcpv6AuxiliaryRegistryStatus, Dhcpv6ClientOro, Dhcpv6OptionPlacementStatus,
Dhcpv6OptionSingleton, Dhcpv6OptionStatus, Dhcpv6RadiusAttributeCode,
Dhcpv6RadiusDhcpv6OptionPermission, Dhcpv6RsooOptionPermission,
Dhcpv6S46PriorityOptionPermission, DHCPV6_OPTION_REGISTRY_EXPLICIT_END,
DHCPV6_OPTION_UNASSIGNED_END, DHCPV6_OPTION_UNASSIGNED_START,
};
#[test]
fn dhcpv6_option_registry_core_rows_include_oro_and_singleton() {
let clientid = dhcpv6_option_meta(1);
assert_eq!(clientid.name, "OPTION_CLIENTID");
assert_eq!(clientid.status, Dhcpv6OptionStatus::Assigned);
assert_eq!(clientid.client_oro, Some(Dhcpv6ClientOro::No));
assert_eq!(clientid.singleton, Some(Dhcpv6OptionSingleton::Yes));
let vendor_opts = dhcpv6_option_meta(17);
assert_eq!(vendor_opts.client_oro, Some(Dhcpv6ClientOro::Optional));
assert_eq!(vendor_opts.singleton, Some(Dhcpv6OptionSingleton::No));
let information_refresh = dhcpv6_option_meta(32);
assert_eq!(
information_refresh.client_oro,
Some(Dhcpv6ClientOro::RequiredForInformationRequest),
);
let sol_max_rt = dhcpv6_option_meta(82);
assert_eq!(
sol_max_rt.client_oro,
Some(Dhcpv6ClientOro::RequiredForSolicit)
);
let v6_dnr = dhcpv6_option_meta(144);
assert_eq!(v6_dnr.name, "OPTION_V6_DNR");
assert_eq!(v6_dnr.singleton, Some(Dhcpv6OptionSingleton::No));
}
#[test]
fn dhcpv6_option_registry_obsolete_reserved_and_unassigned_are_distinct() {
assert_eq!(dhcpv6_option_status(0), Dhcpv6OptionStatus::Reserved);
assert_eq!(dhcpv6_option_name(0), None);
assert_eq!(dhcpv6_option_status(4), Dhcpv6OptionStatus::Obsolete);
assert_eq!(dhcpv6_option_name(4), Some("OPTION_IA_TA"));
assert_eq!(dhcpv6_option_status(12), Dhcpv6OptionStatus::Obsolete);
assert_eq!(dhcpv6_option_status(10), Dhcpv6OptionStatus::Unassigned);
assert_eq!(dhcpv6_option_name(10), None);
assert_eq!(dhcpv6_option_status(35), Dhcpv6OptionStatus::Unassigned);
let trailing = dhcpv6_option_meta(DHCPV6_OPTION_UNASSIGNED_START);
assert_eq!(trailing.name, "Unassigned");
assert_eq!(trailing.status, Dhcpv6OptionStatus::Unassigned);
assert_eq!(trailing.client_oro, None);
assert_eq!(trailing.singleton, None);
assert_eq!(
dhcpv6_option_status(DHCPV6_OPTION_UNASSIGNED_END),
Dhcpv6OptionStatus::Unassigned,
);
}
#[test]
fn dhcpv6_option_registry_explicit_rows_are_indexed_by_code() {
let mut assigned = 0usize;
let mut obsolete = 0usize;
let mut unassigned = 0usize;
let mut reserved = 0usize;
for code in 0..=DHCPV6_OPTION_REGISTRY_EXPLICIT_END {
let meta = dhcpv6_option_meta(code);
assert_eq!(meta.code, code);
assert_ne!(meta.status, Dhcpv6OptionStatus::Unknown);
match meta.status {
Dhcpv6OptionStatus::Assigned => assigned += 1,
Dhcpv6OptionStatus::Obsolete => obsolete += 1,
Dhcpv6OptionStatus::Unassigned => unassigned += 1,
Dhcpv6OptionStatus::Reserved => reserved += 1,
Dhcpv6OptionStatus::Unknown => unreachable!(),
}
}
assert_eq!(assigned, 146);
assert_eq!(obsolete, 2);
assert_eq!(unassigned, 2);
assert_eq!(reserved, 1);
}
#[test]
fn dhcpv6_option_registry_name_only_reports_assigned_rows() {
assert_eq!(dhcpv6_option_name(1), Some("OPTION_CLIENTID"));
assert_eq!(dhcpv6_option_name(4), Some("OPTION_IA_TA"));
assert_eq!(dhcpv6_option_name(10), None);
assert_eq!(dhcpv6_option_name(0), None);
assert_eq!(dhcpv6_option_name(151), None);
}
#[test]
fn dhcpv6_auxiliary_registry_radius_attributes_have_labels() {
let vendor = Dhcpv6RadiusAttributeCode::standard(DHCPV6_RADIUS_ATTRIBUTE_VENDOR_SPECIFIC);
let vendor_meta = dhcpv6_radius_attribute_meta(vendor);
assert_eq!(vendor_meta.code, vendor);
assert_eq!(vendor_meta.name, "Vendor-Specific");
assert_eq!(vendor_meta.status, Dhcpv6AuxiliaryRegistryStatus::Assigned);
assert_eq!(
dhcpv6_radius_attribute_name(vendor),
Some("Vendor-Specific")
);
assert!(dhcpv6_radius_attribute_permitted(vendor));
let options = Dhcpv6RadiusAttributeCode::extended(
DHCPV6_RADIUS_ATTRIBUTE_EXTENDED_TYPE_1,
DHCPV6_RADIUS_ATTRIBUTE_DHCPV6_OPTIONS_EXTENDED_TYPE,
);
assert_eq!(options.type_code(), DHCPV6_RADIUS_ATTRIBUTE_EXTENDED_TYPE_1);
assert_eq!(
options.extended_type(),
Some(DHCPV6_RADIUS_ATTRIBUTE_DHCPV6_OPTIONS_EXTENDED_TYPE)
);
assert_eq!(
dhcpv6_radius_attribute_name(options),
Some("DHCPv6-Options")
);
let unknown = Dhcpv6RadiusAttributeCode::extended(245, 250);
let unknown_meta = dhcpv6_radius_attribute_meta(unknown);
assert_eq!(unknown_meta.code, unknown);
assert_eq!(unknown_meta.name, "Unassigned");
assert_eq!(
unknown_meta.status,
Dhcpv6AuxiliaryRegistryStatus::Unassigned
);
assert_eq!(dhcpv6_radius_attribute_name(unknown), None);
assert!(!dhcpv6_radius_attribute_permitted(unknown));
}
#[test]
fn dhcpv6_auxiliary_registry_supported_transport_preserves_unknown_bits() {
let domtls = dhcpv6_supported_transport_meta(DHCPV6_SUPPORTED_TRANSPORT_DOMTLS_BIT);
assert_eq!(domtls.bit_position, DHCPV6_SUPPORTED_TRANSPORT_DOMTLS_BIT);
assert_eq!(domtls.description, "DNS over mutually authenticated TLS");
assert_eq!(domtls.mnemonic, Some("DomTLS"));
assert_eq!(domtls.status, Dhcpv6AuxiliaryRegistryStatus::Assigned);
assert_eq!(
dhcpv6_supported_transport_name(DHCPV6_SUPPORTED_TRANSPORT_DOMTLS_BIT),
Some("DomTLS")
);
let unassigned = dhcpv6_supported_transport_meta(15);
assert_eq!(unassigned.bit_position, 15);
assert_eq!(unassigned.status, Dhcpv6AuxiliaryRegistryStatus::Unassigned);
assert_eq!(unassigned.mnemonic, None);
let unknown = dhcpv6_supported_transport_meta(250);
assert_eq!(unknown.bit_position, 250);
assert_eq!(unknown.status, Dhcpv6AuxiliaryRegistryStatus::Unknown);
assert_eq!(dhcpv6_supported_transport_name(250), None);
}
#[test]
fn dhcpv6_auxiliary_registry_option_permissions_preserve_unknown_values() {
assert_eq!(
dhcpv6_rsoo_option_permission(DHCPV6_OPTION_ERP_LOCAL_DOMAIN_NAME),
Dhcpv6RsooOptionPermission::Permitted
);
assert!(dhcpv6_rsoo_option_permitted(
DHCPV6_OPTION_ERP_LOCAL_DOMAIN_NAME
));
assert_eq!(
dhcpv6_rsoo_option_permission(DHCPV6_OPTION_RADIUS),
Dhcpv6RsooOptionPermission::NotPermitted
);
assert_eq!(
dhcpv6_s46_priority_option_permission(DHCPV6_OPTION_S46_CONT_MAPE),
Dhcpv6S46PriorityOptionPermission::Permitted
);
assert!(dhcpv6_s46_priority_option_permitted(
DHCPV6_OPTION_S46_CONT_MAPE
));
assert_eq!(
dhcpv6_s46_priority_option_permission(DHCPV6_OPTION_S46_RULE),
Dhcpv6S46PriorityOptionPermission::NotPermitted
);
assert_eq!(
dhcpv6_radius_dhcpv6_option_permission(DHCPV6_OPTION_V6_DNR),
Dhcpv6RadiusDhcpv6OptionPermission::Permitted
);
assert!(dhcpv6_radius_dhcpv6_option_permitted(DHCPV6_OPTION_V6_DNR));
assert_eq!(
dhcpv6_radius_dhcpv6_option_permission(DHCPV6_OPTION_RADIUS),
Dhcpv6RadiusDhcpv6OptionPermission::NotPermitted
);
}
#[test]
fn dhcpv6_option_placement_reports_valid_locations() {
let dns = dhcpv6_option_placement_report(DHCPV6_OPTION_DNS_SERVERS);
assert_eq!(dns.code, DHCPV6_OPTION_DNS_SERVERS);
assert_eq!(dns.registry_status, Dhcpv6OptionStatus::Assigned);
assert_eq!(dns.top_level, Dhcpv6OptionPlacementStatus::Known);
assert_eq!(dns.oro_eligible, Dhcpv6OptionPlacementStatus::Known);
assert_eq!(dns.ia_na, Dhcpv6OptionPlacementStatus::Questionable);
let iaaddr = dhcpv6_option_placement_report(DHCPV6_OPTION_IAADDR);
assert_eq!(iaaddr.top_level, Dhcpv6OptionPlacementStatus::Questionable);
assert_eq!(iaaddr.ia_na, Dhcpv6OptionPlacementStatus::Known);
assert_eq!(iaaddr.ia_pd, Dhcpv6OptionPlacementStatus::Questionable);
let iaprefix = dhcpv6_option_placement_report(DHCPV6_OPTION_IAPREFIX);
assert_eq!(
iaprefix.top_level,
Dhcpv6OptionPlacementStatus::Questionable
);
assert_eq!(iaprefix.ia_pd, Dhcpv6OptionPlacementStatus::Known);
let status = dhcpv6_option_placement_report(DHCPV6_OPTION_STATUS_CODE);
assert_eq!(status.top_level, Dhcpv6OptionPlacementStatus::Known);
assert_eq!(status.ia_na, Dhcpv6OptionPlacementStatus::Known);
assert_eq!(status.ia_pd, Dhcpv6OptionPlacementStatus::Known);
let relay = dhcpv6_option_placement_report(DHCPV6_OPTION_ERP_LOCAL_DOMAIN_NAME);
assert_eq!(relay.relay_supplied, Dhcpv6OptionPlacementStatus::Known);
}
#[test]
fn dhcpv6_option_placement_reports_questionable_locations() {
assert!(dhcpv6_option_top_level_placement(DHCPV6_OPTION_IAADDR).is_questionable());
assert!(dhcpv6_option_ia_na_placement(DHCPV6_OPTION_DNS_SERVERS).is_questionable());
assert!(dhcpv6_option_oro_placement(DHCPV6_OPTION_CLIENTID).is_questionable());
let clientid = dhcpv6_option_placement_report(DHCPV6_OPTION_CLIENTID);
assert_eq!(clientid.top_level, Dhcpv6OptionPlacementStatus::Known);
assert_eq!(clientid.ia_na, Dhcpv6OptionPlacementStatus::Questionable);
assert_eq!(
clientid.relay_supplied,
Dhcpv6OptionPlacementStatus::Questionable
);
}
#[test]
fn dhcpv6_option_placement_reports_unknown_options_without_losing_codepoints() {
let unknown = dhcpv6_option_placement_report(65_000);
assert_eq!(unknown.code, 65_000);
assert_eq!(unknown.registry_status, Dhcpv6OptionStatus::Unassigned);
assert_eq!(unknown.top_level, Dhcpv6OptionPlacementStatus::Unknown);
assert_eq!(unknown.ia_na, Dhcpv6OptionPlacementStatus::Unknown);
assert_eq!(unknown.ia_pd, Dhcpv6OptionPlacementStatus::Unknown);
assert_eq!(unknown.relay_supplied, Dhcpv6OptionPlacementStatus::Unknown);
assert!(unknown.oro_eligible.is_unknown());
}
}