1 use crate::{err, ArpHardwareId, EtherType, LinuxNonstandardEtherType}; 2 3 /// Represents the "protcol type" field in a Linux Cooked Capture v1 packet. It 4 /// is represented as an enum due to the meaning of the inner value depending 5 /// on the associated arp_hardware_id field. 6 /// 7 /// You can convert pairs of ArpHardwareId and its associated u16 value with ` 8 /// LinuxSllProtocolType::try_from()`, an Err(_) is returned if the relation is 9 /// not defined or known. 10 /// 11 /// ``` 12 /// use etherparse::LinuxNonstandardEtherType; 13 /// 14 /// // Convert to LinuxNonstandardEtherType using the from & into trait 15 /// let link_type: LinuxNonstandardEtherType = 0x0001.try_into().unwrap(); 16 /// assert_eq!(LinuxNonstandardEtherType::N802_3, link_type); 17 /// 18 /// // convert to u16 using the from & into trait 19 /// let num: u16 = LinuxNonstandardEtherType::N802_3.try_into().unwrap(); 20 /// assert_eq!(0x0001, num); 21 /// ``` 22 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 23 pub enum LinuxSllProtocolType { 24 /// The protocol type should be ignored 25 Ignored(u16), 26 /// Netlink protocol type of the encapsulated payload 27 NetlinkProtocolType(u16), 28 /// Generic Routing Encapsulation protocol type for the encapsulated payload 29 GenericRoutingEncapsulationProtocolType(u16), 30 /// EtherType of the encapsulated payload 31 EtherType(EtherType), 32 /// Non-standard ether types of the encapsulated payload 33 LinuxNonstandardEtherType(LinuxNonstandardEtherType), 34 } 35 36 impl LinuxSllProtocolType { 37 pub const SUPPORTED_ARPHWD: [ArpHardwareId; 5] = [ 38 ArpHardwareId::NETLINK, 39 ArpHardwareId::IPGRE, 40 ArpHardwareId::IEEE80211_RADIOTAP, 41 ArpHardwareId::FRAD, 42 ArpHardwareId::ETHERNET, 43 ]; 44 change_value(&mut self, value: u16)45 pub fn change_value(&mut self, value: u16) { 46 *self = match *self { 47 LinuxSllProtocolType::Ignored(_) => LinuxSllProtocolType::Ignored(value), 48 LinuxSllProtocolType::NetlinkProtocolType(_) => { 49 LinuxSllProtocolType::NetlinkProtocolType(value) 50 } 51 LinuxSllProtocolType::GenericRoutingEncapsulationProtocolType(_) => { 52 LinuxSllProtocolType::GenericRoutingEncapsulationProtocolType(value) 53 } 54 LinuxSllProtocolType::EtherType(_) 55 | LinuxSllProtocolType::LinuxNonstandardEtherType(_) => { 56 match LinuxNonstandardEtherType::try_from(value) { 57 Ok(v) => LinuxSllProtocolType::LinuxNonstandardEtherType(v), 58 Err(_) => LinuxSllProtocolType::EtherType(EtherType(value)), 59 } 60 } 61 } 62 } 63 } 64 65 impl TryFrom<(ArpHardwareId, u16)> for LinuxSllProtocolType { 66 type Error = err::linux_sll::HeaderError; 67 try_from( (arp_hardware_id, protocol_type): (ArpHardwareId, u16), ) -> Result<Self, Self::Error>68 fn try_from( 69 (arp_hardware_id, protocol_type): (ArpHardwareId, u16), 70 ) -> Result<Self, Self::Error> { 71 match arp_hardware_id { 72 ArpHardwareId::NETLINK => Ok(LinuxSllProtocolType::NetlinkProtocolType(protocol_type)), 73 ArpHardwareId::IPGRE => { 74 Ok(LinuxSllProtocolType::GenericRoutingEncapsulationProtocolType(protocol_type)) 75 } 76 ArpHardwareId::IEEE80211_RADIOTAP => Ok(LinuxSllProtocolType::Ignored(protocol_type)), 77 ArpHardwareId::FRAD => Ok(LinuxSllProtocolType::Ignored(protocol_type)), 78 ArpHardwareId::ETHERNET => match LinuxNonstandardEtherType::try_from(protocol_type) { 79 Ok(v) => Ok(LinuxSllProtocolType::LinuxNonstandardEtherType(v)), 80 Err(_) => Ok(LinuxSllProtocolType::EtherType(EtherType(protocol_type))), 81 }, 82 _ => Err(err::linux_sll::HeaderError::UnsupportedArpHardwareId { 83 arp_hardware_type: arp_hardware_id, 84 }), 85 } 86 } 87 } 88 89 impl From<LinuxSllProtocolType> for u16 { from(value: LinuxSllProtocolType) -> u1690 fn from(value: LinuxSllProtocolType) -> u16 { 91 match value { 92 LinuxSllProtocolType::Ignored(value) => value, 93 LinuxSllProtocolType::NetlinkProtocolType(value) => value, 94 LinuxSllProtocolType::GenericRoutingEncapsulationProtocolType(value) => value, 95 LinuxSllProtocolType::EtherType(value) => value.into(), 96 LinuxSllProtocolType::LinuxNonstandardEtherType(value) => value.into(), 97 } 98 } 99 } 100 101 #[cfg(test)] 102 mod test { 103 use super::*; 104 105 #[test] try_from_pair_arp_hardware_id_u16()106 fn try_from_pair_arp_hardware_id_u16() { 107 assert_eq!( 108 LinuxSllProtocolType::try_from((ArpHardwareId::NETLINK, 123)), 109 Ok(LinuxSllProtocolType::NetlinkProtocolType(123)) 110 ); 111 assert_eq!( 112 LinuxSllProtocolType::try_from((ArpHardwareId::IPGRE, 123)), 113 Ok(LinuxSllProtocolType::GenericRoutingEncapsulationProtocolType(123)) 114 ); 115 assert_eq!( 116 LinuxSllProtocolType::try_from((ArpHardwareId::IEEE80211_RADIOTAP, 123)), 117 Ok(LinuxSllProtocolType::Ignored(123)) 118 ); 119 assert_eq!( 120 LinuxSllProtocolType::try_from((ArpHardwareId::FRAD, 123)), 121 Ok(LinuxSllProtocolType::Ignored(123)) 122 ); 123 assert_eq!( 124 LinuxSllProtocolType::try_from(( 125 ArpHardwareId::ETHERNET, 126 u16::from(LinuxNonstandardEtherType::N802_3) 127 )), 128 Ok(LinuxSllProtocolType::LinuxNonstandardEtherType( 129 LinuxNonstandardEtherType::N802_3 130 )) 131 ); 132 assert_eq!( 133 LinuxSllProtocolType::try_from((ArpHardwareId::ETHERNET, u16::from(EtherType::IPV4))), 134 Ok(LinuxSllProtocolType::EtherType(EtherType::IPV4)) 135 ); 136 } 137 } 138