cross_socket/packet/
ethernet.rs

1use crate::datalink::MacAddr;
2use pnet::packet::Packet;
3
4/// Represents the Ethernet header length.
5pub const ETHERNET_HEADER_LEN: usize = 14;
6
7/// Represents the Ethernet types.
8#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
9pub enum EtherType {
10    Ipv4,
11    Arp,
12    WakeOnLan,
13    Trill,
14    DECnet,
15    Rarp,
16    AppleTalk,
17    Aarp,
18    Ipx,
19    Qnx,
20    Ipv6,
21    FlowControl,
22    CobraNet,
23    Mpls,
24    MplsMcast,
25    PppoeDiscovery,
26    PppoeSession,
27    Vlan,
28    PBridge,
29    Lldp,
30    Ptp,
31    Cfm,
32    QinQ,
33    Unknown(u16),
34}
35
36impl EtherType {
37    /// Constructs a new EtherType from u16
38    pub fn from_u16(n: u16) -> Option<EtherType> {
39        match n {
40            0x0800 => Some(EtherType::Ipv4),
41            0x0806 => Some(EtherType::Arp),
42            0x0842 => Some(EtherType::WakeOnLan),
43            0x22F3 => Some(EtherType::Trill),
44            0x6003 => Some(EtherType::DECnet),
45            0x8035 => Some(EtherType::Rarp),
46            0x809B => Some(EtherType::AppleTalk),
47            0x80F3 => Some(EtherType::Aarp),
48            0x8137 => Some(EtherType::Ipx),
49            0x8204 => Some(EtherType::Qnx),
50            0x86DD => Some(EtherType::Ipv6),
51            0x8808 => Some(EtherType::FlowControl),
52            0x8819 => Some(EtherType::CobraNet),
53            0x8847 => Some(EtherType::Mpls),
54            0x8848 => Some(EtherType::MplsMcast),
55            0x8863 => Some(EtherType::PppoeDiscovery),
56            0x8864 => Some(EtherType::PppoeSession),
57            0x8100 => Some(EtherType::Vlan),
58            0x88a8 => Some(EtherType::PBridge),
59            0x88cc => Some(EtherType::Lldp),
60            0x88f7 => Some(EtherType::Ptp),
61            0x8902 => Some(EtherType::Cfm),
62            0x9100 => Some(EtherType::QinQ),
63            _ => Some(EtherType::Unknown(n)),
64        }
65    }
66    /// Return the number of the EtherType
67    pub fn number(&self) -> u16 {
68        match *self {
69            EtherType::Ipv4 => 0x0800,
70            EtherType::Arp => 0x0806,
71            EtherType::WakeOnLan => 0x0842,
72            EtherType::Trill => 0x22F3,
73            EtherType::DECnet => 0x6003,
74            EtherType::Rarp => 0x8035,
75            EtherType::AppleTalk => 0x809B,
76            EtherType::Aarp => 0x80F3,
77            EtherType::Ipx => 0x8137,
78            EtherType::Qnx => 0x8204,
79            EtherType::Ipv6 => 0x86DD,
80            EtherType::FlowControl => 0x8808,
81            EtherType::CobraNet => 0x8819,
82            EtherType::Mpls => 0x8847,
83            EtherType::MplsMcast => 0x8848,
84            EtherType::PppoeDiscovery => 0x8863,
85            EtherType::PppoeSession => 0x8864,
86            EtherType::Vlan => 0x8100,
87            EtherType::PBridge => 0x88a8,
88            EtherType::Lldp => 0x88cc,
89            EtherType::Ptp => 0x88f7,
90            EtherType::Cfm => 0x8902,
91            EtherType::QinQ => 0x9100,
92            EtherType::Unknown(n) => n,
93        }
94    }
95    /// Return the name of the EtherType
96    pub fn name(&self) -> &str {
97        match *self {
98            EtherType::Ipv4 => "IPv4",
99            EtherType::Arp => "ARP",
100            EtherType::WakeOnLan => "WakeOnLan",
101            EtherType::Trill => "Trill",
102            EtherType::DECnet => "DECnet",
103            EtherType::Rarp => "RARP",
104            EtherType::AppleTalk => "AppleTalk",
105            EtherType::Aarp => "AARP",
106            EtherType::Ipx => "IPX",
107            EtherType::Qnx => "QNX",
108            EtherType::Ipv6 => "IPv6",
109            EtherType::FlowControl => "FlowControl",
110            EtherType::CobraNet => "CobraNet",
111            EtherType::Mpls => "MPLS",
112            EtherType::MplsMcast => "MPLS Multicast",
113            EtherType::PppoeDiscovery => "PPPoE Discovery",
114            EtherType::PppoeSession => "PPPoE Session",
115            EtherType::Vlan => "VLAN",
116            EtherType::PBridge => "Provider Bridging",
117            EtherType::Lldp => "LLDP",
118            EtherType::Ptp => "PTP",
119            EtherType::Cfm => "CFM",
120            EtherType::QinQ => "QinQ",
121            EtherType::Unknown(_) => "Unknown",
122        }
123    }
124}
125
126/// Represents an Ethernet packet.
127#[derive(Clone, Debug)]
128pub struct EthernetPacket {
129    /// Destination MAC address
130    pub destination: MacAddr,
131    /// Source MAC address
132    pub source: MacAddr,
133    /// EtherType
134    pub ethertype: EtherType,
135    /// Payload. Next level protocol packet.
136    pub payload: Vec<u8>,
137}
138
139impl EthernetPacket {
140    /// Constructs a new EthernetPacket from pnet::packet::ethernet::EthernetPacket.
141    pub(crate) fn from_pnet_packet(
142        packet: &pnet::packet::ethernet::EthernetPacket,
143    ) -> EthernetPacket {
144        EthernetPacket {
145            destination: MacAddr::new(packet.get_destination().octets()),
146            source: MacAddr::new(packet.get_source().octets()),
147            ethertype: EtherType::from_u16(packet.get_ethertype().0).unwrap(),
148            payload: packet.payload().to_vec(),
149        }
150    }
151    /// Constructs a new EthernetPacket from bytes
152    pub fn from_bytes(packet: &[u8]) -> EthernetPacket {
153        let ethernet_packet = pnet::packet::ethernet::EthernetPacket::new(packet).unwrap();
154        EthernetPacket::from_pnet_packet(&ethernet_packet)
155    }
156}
157
158/// Build Ethernet packet
159pub(crate) fn build_ethernet_packet(
160    eth_packet: &mut pnet::packet::ethernet::MutableEthernetPacket,
161    src_mac: MacAddr,
162    dst_mac: MacAddr,
163    ether_type: EtherType,
164) {
165    eth_packet.set_source(pnet::datalink::MacAddr::from(src_mac.octets()));
166    eth_packet.set_destination(pnet::datalink::MacAddr::from(dst_mac.octets()));
167    match ether_type {
168        EtherType::Arp => {
169            eth_packet.set_ethertype(pnet::packet::ethernet::EtherTypes::Arp);
170        }
171        EtherType::Ipv4 => {
172            eth_packet.set_ethertype(pnet::packet::ethernet::EtherTypes::Ipv4);
173        }
174        EtherType::Ipv6 => {
175            eth_packet.set_ethertype(pnet::packet::ethernet::EtherTypes::Ipv6);
176        }
177        _ => {
178            // TODO
179        }
180    }
181}
182
183/// Build Ethernet ARP packet
184pub(crate) fn build_ethernet_arp_packet(
185    eth_packet: &mut pnet::packet::ethernet::MutableEthernetPacket,
186    src_mac: MacAddr,
187) {
188    eth_packet.set_source(pnet::datalink::MacAddr::from(src_mac.octets()));
189    eth_packet.set_destination(pnet::datalink::MacAddr::broadcast());
190    eth_packet.set_ethertype(pnet::packet::ethernet::EtherTypes::Arp);
191}
192
193/// Ethernet Packet Builder
194#[derive(Clone, Debug)]
195pub struct EthernetPacketBuilder {
196    /// Source MAC address
197    pub src_mac: MacAddr,
198    /// Destination MAC address
199    pub dst_mac: MacAddr,
200    /// EtherType
201    pub ether_type: EtherType,
202}
203
204impl EthernetPacketBuilder {
205    /// Constructs a new EthernetPacketBuilder
206    pub fn new() -> EthernetPacketBuilder {
207        EthernetPacketBuilder {
208            src_mac: MacAddr::new([0; 6]),
209            dst_mac: MacAddr::new([0; 6]),
210            ether_type: EtherType::Ipv4,
211        }
212    }
213    /// Build Ethernet packet and return bytes
214    pub fn build(&self) -> Vec<u8> {
215        let mut buffer: Vec<u8> = vec![0; ETHERNET_HEADER_LEN];
216        let mut eth_packet =
217            pnet::packet::ethernet::MutableEthernetPacket::new(&mut buffer).unwrap();
218        build_ethernet_packet(
219            &mut eth_packet,
220            self.src_mac.clone(),
221            self.dst_mac.clone(),
222            self.ether_type,
223        );
224        eth_packet.to_immutable().packet().to_vec()
225    }
226}
227
228/// Create Dummy Ethernet Frame
229pub(crate) fn create_dummy_ethernet_frame(
230    payload_offset: usize,
231    packet: &[u8],
232) -> Vec<u8> {
233    if packet.len() <= payload_offset {
234        return packet.to_vec();
235    }
236    let buffer_size: usize = packet.len() + ETHERNET_HEADER_LEN - payload_offset;
237    let mut buffer: Vec<u8> = vec![0; buffer_size];
238    let src_mac: MacAddr = MacAddr::zero();
239    let dst_mac: MacAddr = MacAddr::zero();
240    let mut ether_type: EtherType = EtherType::Unknown(0);
241    let mut eth_packet = pnet::packet::ethernet::MutableEthernetPacket::new(&mut buffer).unwrap();
242    if let Some (ip_packet) = pnet::packet::ipv4::Ipv4Packet::new(&packet[payload_offset..]) {
243        let version = ip_packet.get_version();
244        if version == 4 {
245            ether_type = EtherType::Ipv4;
246        }
247        else if version == 6 {
248            ether_type = EtherType::Ipv6;
249        }
250    }
251    build_ethernet_packet(&mut eth_packet, src_mac, dst_mac, ether_type);
252    eth_packet.set_payload(&packet[payload_offset..]);
253    eth_packet.to_immutable().packet().to_vec()
254}