• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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