1use crate::datalink::MacAddr;
2use pnet::packet::Packet;
3
4pub const ETHERNET_HEADER_LEN: usize = 14;
6
7#[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 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 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 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#[derive(Clone, Debug)]
128pub struct EthernetPacket {
129 pub destination: MacAddr,
131 pub source: MacAddr,
133 pub ethertype: EtherType,
135 pub payload: Vec<u8>,
137}
138
139impl EthernetPacket {
140 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 pub fn from_bytes(packet: &[u8]) -> EthernetPacket {
153 let ethernet_packet = pnet::packet::ethernet::EthernetPacket::new(packet).unwrap();
154 EthernetPacket::from_pnet_packet(ðernet_packet)
155 }
156}
157
158pub(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 }
180 }
181}
182
183pub(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#[derive(Clone, Debug)]
195pub struct EthernetPacketBuilder {
196 pub src_mac: MacAddr,
198 pub dst_mac: MacAddr,
200 pub ether_type: EtherType,
202}
203
204impl EthernetPacketBuilder {
205 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 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
228pub(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}