1 use super::*; 2 3 /// "Destination Unreachable" ICMPv6 code containing a reason why a 4 /// destination could not be reached. 5 /// 6 /// # RFC 4443 Description: 7 /// 8 /// A Destination Unreachable message SHOULD be generated by a router, or 9 /// by the IPv6 layer in the originating node, in response to a packet 10 /// that cannot be delivered to its destination address for reasons other 11 /// than congestion. (An ICMPv6 message MUST NOT be generated if a 12 /// packet is dropped due to congestion.) 13 #[derive(Clone, Copy, Debug, PartialEq, Eq)] 14 pub enum DestUnreachableCode { 15 /// No route to destination 16 NoRoute = 0, 17 /// Communication with destination administratively prohibited 18 Prohibited = 1, 19 /// Beyond scope of source address 20 BeyondScope = 2, 21 /// Address unreachable 22 Address = 3, 23 /// Port unreachable 24 Port = 4, 25 /// Source address failed ingress/egress policy 26 SourceAddressFailedPolicy = 5, 27 /// Reject route to destination 28 RejectRoute = 6, 29 } 30 31 impl DestUnreachableCode { 32 /// Converts the u8 code value from an ICMPv6 "destination unreachable" 33 /// packet to an `icmpv6::DestUnreachableCode` enum. 34 /// 35 /// # Example Usage: 36 /// 37 /// ``` 38 /// use etherparse::{icmpv6, icmpv6::DestUnreachableCode}; 39 /// let icmp_packet: [u8;8] = [ 40 /// icmpv6::TYPE_DST_UNREACH, icmpv6::CODE_DST_UNREACH_PORT, 0, 0, 41 /// 0, 0, 0, 0, 42 /// ]; 43 /// 44 /// if icmpv6::TYPE_DST_UNREACH == icmp_packet[0] { 45 /// let dst = icmpv6::DestUnreachableCode::from_u8( 46 /// icmp_packet[1] 47 /// ); 48 /// assert_eq!(dst, Some(icmpv6::DestUnreachableCode::Port)); 49 /// } 50 /// ``` from_u8(code_u8: u8) -> Option<DestUnreachableCode>51 pub fn from_u8(code_u8: u8) -> Option<DestUnreachableCode> { 52 use DestUnreachableCode::*; 53 match code_u8 { 54 CODE_DST_UNREACH_NO_ROUTE => Some(NoRoute), 55 CODE_DST_UNREACH_PROHIBITED => Some(Prohibited), 56 CODE_DST_UNREACH_BEYOND_SCOPE => Some(BeyondScope), 57 CODE_DST_UNREACH_ADDR => Some(Address), 58 CODE_DST_UNREACH_PORT => Some(Port), 59 CODE_DST_UNREACH_SOURCE_ADDRESS_FAILED_POLICY => Some(SourceAddressFailedPolicy), 60 CODE_DST_UNREACH_REJECT_ROUTE_TO_DEST => Some(RejectRoute), 61 _ => None, 62 } 63 } 64 65 /// Returns the code value of the destination unreachable packet. 66 /// 67 /// This is the second byte of an ICMPv6 packet. 68 #[inline] code_u8(&self) -> u869 pub fn code_u8(&self) -> u8 { 70 *self as u8 71 } 72 } 73 74 #[cfg(test)] 75 pub(crate) mod dest_unreachable_code_test_consts { 76 use super::{DestUnreachableCode::*, *}; 77 78 pub const VALID_VALUES: [(DestUnreachableCode, u8); 7] = [ 79 (NoRoute, CODE_DST_UNREACH_NO_ROUTE), 80 (Prohibited, CODE_DST_UNREACH_PROHIBITED), 81 (BeyondScope, CODE_DST_UNREACH_BEYOND_SCOPE), 82 (Address, CODE_DST_UNREACH_ADDR), 83 (Port, CODE_DST_UNREACH_PORT), 84 ( 85 SourceAddressFailedPolicy, 86 CODE_DST_UNREACH_SOURCE_ADDRESS_FAILED_POLICY, 87 ), 88 (RejectRoute, CODE_DST_UNREACH_REJECT_ROUTE_TO_DEST), 89 ]; 90 } 91 92 #[cfg(test)] 93 mod test { 94 use super::{dest_unreachable_code_test_consts::*, DestUnreachableCode::*, *}; 95 use alloc::format; 96 97 #[test] from_u8()98 fn from_u8() { 99 for (code, code_u8) in VALID_VALUES { 100 assert_eq!(code, DestUnreachableCode::from_u8(code_u8).unwrap()); 101 } 102 for code_u8 in 7u8..=0xff { 103 assert!(DestUnreachableCode::from_u8(code_u8).is_none()); 104 } 105 } 106 107 #[test] code_u8()108 fn code_u8() { 109 for (code, code_u8) in VALID_VALUES { 110 assert_eq!(code.code_u8(), code_u8); 111 } 112 } 113 114 #[test] clone_eq()115 fn clone_eq() { 116 for (code, _) in VALID_VALUES { 117 assert_eq!(code.clone(), code); 118 } 119 } 120 121 #[test] debug()122 fn debug() { 123 let tests = [ 124 (NoRoute, "NoRoute"), 125 (Prohibited, "Prohibited"), 126 (BeyondScope, "BeyondScope"), 127 (Address, "Address"), 128 (Port, "Port"), 129 (SourceAddressFailedPolicy, "SourceAddressFailedPolicy"), 130 (RejectRoute, "RejectRoute"), 131 ]; 132 for test in tests { 133 assert_eq!(format!("{:?}", test.0), test.1); 134 } 135 } 136 } 137