1 use super::*;
2 
3 /// Code values for ICMPv6 parameter problem messages.
4 ///
5 /// Source: <https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xhtml#icmpv6-parameters-codes-5>
6 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
7 pub enum ParameterProblemCode {
8     /// Erroneous header field encountered (from [RFC 4443](https://tools.ietf.org/html/rfc4443))
9     ErroneousHeaderField = 0,
10     /// Unrecognized Next Header type encountered (from [RFC 4443](https://tools.ietf.org/html/rfc4443))
11     UnrecognizedNextHeader = 1,
12     /// Unrecognized IPv6 option encountered (from [RFC 4443](https://tools.ietf.org/html/rfc4443))
13     UnrecognizedIpv6Option = 2,
14     /// IPv6 First Fragment has incomplete IPv6 Header Chain (from [RFC 7112](https://tools.ietf.org/html/rfc7112))
15     Ipv6FirstFragmentIncompleteHeaderChain = 3,
16     /// SR Upper-layer Header Error (from [RFC 8754](https://tools.ietf.org/html/rfc8754)).
17     SrUpperLayerHeaderError = 4,
18     /// Unrecognized Next Header type encountered by intermediate node (from [RFC 8883](https://tools.ietf.org/html/rfc8883))
19     UnrecognizedNextHeaderByIntermediateNode = 5,
20     /// Extension header too big (from [RFC 8883](https://tools.ietf.org/html/rfc8883))
21     ExtensionHeaderTooBig = 6,
22     /// Extension header chain too long (from [RFC 8883](https://tools.ietf.org/html/rfc8883))
23     ExtensionHeaderChainTooLong = 7,
24     /// Too many extension headers (from [RFC 8883](https://tools.ietf.org/html/rfc8883))
25     TooManyExtensionHeaders = 8,
26     /// Too many options in extension header (from [RFC 8883](https://tools.ietf.org/html/rfc8883))
27     TooManyOptionsInExtensionHeader = 9,
28     /// Option too big (from [RFC 8883](https://tools.ietf.org/html/rfc8883))
29     OptionTooBig = 10,
30 }
31 
32 impl ParameterProblemCode {
33     /// Tries to convert a code [`u8`] value to a [`ParameterProblemCode`] value.
34     ///
35     /// Returns [`None`] in case the code value is not known as a parameter problem code.
from_u8(code_u8: u8) -> Option<ParameterProblemCode>36     pub fn from_u8(code_u8: u8) -> Option<ParameterProblemCode> {
37         use ParameterProblemCode::*;
38         match code_u8 {
39             CODE_PARAM_PROBLEM_ERR_HEADER_FIELD => Some(ErroneousHeaderField),
40             CODE_PARAM_PROBLEM_UNRECOG_NEXT_HEADER => Some(UnrecognizedNextHeader),
41             CODE_PARAM_PROBLEM_UNRECOG_IPV6_OPTION => Some(UnrecognizedIpv6Option),
42             CODE_PARAM_PROBLEM_IPV6_FIRST_FRAG_INCOMP_HEADER_CHAIN => {
43                 Some(Ipv6FirstFragmentIncompleteHeaderChain)
44             }
45             CODE_PARAM_PROBLEM_SR_UPPER_LAYER_HEADER_ERROR => Some(SrUpperLayerHeaderError),
46             CODE_PARAM_PROBLEM_UNRECOG_NEXT_HEADER_BY_INTERMEDIATE_NODE => {
47                 Some(UnrecognizedNextHeaderByIntermediateNode)
48             }
49             CODE_PARAM_PROBLEM_EXT_HEADER_TOO_BIG => Some(ExtensionHeaderTooBig),
50             CODE_PARAM_PROBLEM_EXT_HEADER_CHAIN_TOO_LONG => Some(ExtensionHeaderChainTooLong),
51             CODE_PARAM_PROBLEM_TOO_MANY_EXT_HEADERS => Some(TooManyExtensionHeaders),
52             CODE_PARAM_PROBLEM_TOO_MANY_OPTIONS_EXT_HEADER => Some(TooManyOptionsInExtensionHeader),
53             CODE_PARAM_PROBLEM_OPTION_TOO_BIG => Some(OptionTooBig),
54             _ => None,
55         }
56     }
57 
58     /// Returns the [`u8`] value of the code.
59     #[inline]
code_u8(&self) -> u860     pub fn code_u8(&self) -> u8 {
61         *self as u8
62     }
63 }
64 
65 #[cfg(test)]
66 pub(crate) mod parameter_problem_code_test_consts {
67     use super::*;
68     use ParameterProblemCode::*;
69 
70     pub const VALID_VALUES: [(ParameterProblemCode, u8); 11] = [
71         (ErroneousHeaderField, CODE_PARAM_PROBLEM_ERR_HEADER_FIELD),
72         (
73             UnrecognizedNextHeader,
74             CODE_PARAM_PROBLEM_UNRECOG_NEXT_HEADER,
75         ),
76         (
77             UnrecognizedIpv6Option,
78             CODE_PARAM_PROBLEM_UNRECOG_IPV6_OPTION,
79         ),
80         (
81             Ipv6FirstFragmentIncompleteHeaderChain,
82             CODE_PARAM_PROBLEM_IPV6_FIRST_FRAG_INCOMP_HEADER_CHAIN,
83         ),
84         (
85             SrUpperLayerHeaderError,
86             CODE_PARAM_PROBLEM_SR_UPPER_LAYER_HEADER_ERROR,
87         ),
88         (
89             UnrecognizedNextHeaderByIntermediateNode,
90             CODE_PARAM_PROBLEM_UNRECOG_NEXT_HEADER_BY_INTERMEDIATE_NODE,
91         ),
92         (ExtensionHeaderTooBig, CODE_PARAM_PROBLEM_EXT_HEADER_TOO_BIG),
93         (
94             ExtensionHeaderChainTooLong,
95             CODE_PARAM_PROBLEM_EXT_HEADER_CHAIN_TOO_LONG,
96         ),
97         (
98             TooManyExtensionHeaders,
99             CODE_PARAM_PROBLEM_TOO_MANY_EXT_HEADERS,
100         ),
101         (
102             TooManyOptionsInExtensionHeader,
103             CODE_PARAM_PROBLEM_TOO_MANY_OPTIONS_EXT_HEADER,
104         ),
105         (OptionTooBig, CODE_PARAM_PROBLEM_OPTION_TOO_BIG),
106     ];
107 }
108 
109 #[cfg(test)]
110 mod test {
111     use super::{parameter_problem_code_test_consts::*, ParameterProblemCode::*, *};
112     use alloc::format;
113 
114     #[test]
from_u8()115     fn from_u8() {
116         for t in VALID_VALUES {
117             assert_eq!(Some(t.0), ParameterProblemCode::from_u8(t.1));
118         }
119 
120         for code_u8 in 11..=u8::MAX {
121             assert_eq!(None, ParameterProblemCode::from_u8(code_u8));
122         }
123     }
124 
125     #[test]
code_u8()126     fn code_u8() {
127         for t in VALID_VALUES {
128             assert_eq!(t.0.code_u8(), t.1);
129         }
130     }
131     #[test]
clone_eq()132     fn clone_eq() {
133         for (value, _) in VALID_VALUES {
134             assert_eq!(value.clone(), value);
135         }
136     }
137 
138     #[test]
debug()139     fn debug() {
140         let tests = [
141             (ErroneousHeaderField, "ErroneousHeaderField"),
142             (UnrecognizedNextHeader, "UnrecognizedNextHeader"),
143             (UnrecognizedIpv6Option, "UnrecognizedIpv6Option"),
144             (UnrecognizedNextHeader, "UnrecognizedNextHeader"),
145             (UnrecognizedIpv6Option, "UnrecognizedIpv6Option"),
146             (
147                 Ipv6FirstFragmentIncompleteHeaderChain,
148                 "Ipv6FirstFragmentIncompleteHeaderChain",
149             ),
150             (SrUpperLayerHeaderError, "SrUpperLayerHeaderError"),
151             (
152                 UnrecognizedNextHeaderByIntermediateNode,
153                 "UnrecognizedNextHeaderByIntermediateNode",
154             ),
155             (ExtensionHeaderTooBig, "ExtensionHeaderTooBig"),
156             (ExtensionHeaderChainTooLong, "ExtensionHeaderChainTooLong"),
157             (TooManyExtensionHeaders, "TooManyExtensionHeaders"),
158             (
159                 TooManyOptionsInExtensionHeader,
160                 "TooManyOptionsInExtensionHeader",
161             ),
162             (OptionTooBig, "OptionTooBig"),
163         ];
164         for test in tests {
165             assert_eq!(format!("{:?}", test.0), test.1);
166         }
167     }
168 }
169