1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
use std::cmp::max; use std::fmt::{Display, Formatter, Result as FmtResult}; use std::net::{Ipv4Addr, Ipv6Addr}; const MASK: u8 = 0b1111_1111; #[derive(Debug, PartialEq, Clone, Eq, Hash)] pub enum Address { Ipv4(Ipv4Addr), Ipv6(Ipv6Addr), } impl Display for Address { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { match self { Address::Ipv4(ipv4_addr) => ipv4_addr.fmt(f), Address::Ipv6(ipv6_addr) => ipv6_addr.fmt(f), } } } impl Address { pub fn get_address_number(&self) -> AddressNumber { match self { Address::Ipv4(_) => AddressNumber::Ipv4, Address::Ipv6(_) => AddressNumber::Ipv6, } } } #[derive(Debug, Clone, FromPrimitive, ToPrimitive, PartialEq, Eq, Hash)] pub enum AddressNumber { Ipv4 = 0x0001, Ipv6 = 0x0002, } #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum ECSError { Ipv4PrefixError(u8), Ipv4MaskError(Ipv4Addr, u8), Ipv6PrefixError(u8), Ipv6MaskError(Ipv6Addr, u8), } #[derive(Debug, PartialEq, Clone, Eq, Hash)] pub struct ECS { pub(crate) source_prefix_length: u8, pub(crate) scope_prefix_length: u8, pub(crate) address: Address, } fn check_ipv4_addr(ipv4_addr: &Ipv4Addr, prefix_length: u8) -> Result<(), ECSError> { if 32 < prefix_length { return Err(ECSError::Ipv4PrefixError(prefix_length)); } else if 32 == prefix_length { return Ok(()); } let octects = ipv4_addr.octets(); let index = (prefix_length / 8) as usize; let remain = prefix_length % 8; if (octects[index] & (MASK >> remain)) != 0 { return Err(ECSError::Ipv4MaskError(*ipv4_addr, prefix_length)); } let (_, octects_right) = octects.split_at(index + 1); for b in octects_right { if *b != 0 { return Err(ECSError::Ipv4MaskError(*ipv4_addr, prefix_length)); } } Ok(()) } fn check_ipv6_addr(ipv6_addr: &Ipv6Addr, prefix_length: u8) -> Result<(), ECSError> { if 128 < prefix_length { return Err(ECSError::Ipv6PrefixError(prefix_length)); } else if 128 == prefix_length { return Ok(()); } let octects = ipv6_addr.octets(); let index = (prefix_length / 8) as usize; let remain = prefix_length % 8; if (octects[index] & (MASK >> remain)) != 0 { return Err(ECSError::Ipv6MaskError(*ipv6_addr, prefix_length)); } let (_, octects_right) = octects.split_at(index + 1); for b in octects_right { if *b != 0 { return Err(ECSError::Ipv6MaskError(*ipv6_addr, prefix_length)); } } Ok(()) } impl ECS { pub fn new( source_prefix_length: u8, scope_prefix_length: u8, address: Address, ) -> Result<ECS, ECSError> { let prefix_length = max(source_prefix_length, scope_prefix_length); match &address { Address::Ipv4(ipv4_addr) => check_ipv4_addr(ipv4_addr, prefix_length)?, Address::Ipv6(ipv6_addr) => check_ipv6_addr(ipv6_addr, prefix_length)?, } let ecs = ECS { source_prefix_length, scope_prefix_length, address, }; Ok(ecs) } } impl Display for ECS { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { write!( f, "{} {} {}", self.source_prefix_length, self.scope_prefix_length, self.address ) } }