packet_dissector_ethernet/
lib.rs1#![deny(missing_docs)]
17
18use packet_dissector_core::dissector::{DispatchHint, DissectResult, Dissector};
19use packet_dissector_core::error::PacketError;
20use packet_dissector_core::field::{FieldDescriptor, FieldType, FieldValue, MacAddr};
21use packet_dissector_core::packet::DissectBuffer;
22use packet_dissector_core::util::read_be_u16;
23
24const HEADER_SIZE: usize = 14;
27
28const TPID_8021Q: u16 = 0x8100;
31
32const TPID_8021AD: u16 = 0x88A8;
36
37const ETHERTYPE_MIN: u16 = 0x0600;
41
42const LENGTH_MAX: u16 = 0x05DC;
45
46const LLC_HEADER_SIZE: usize = 3;
49
50const FD_DST: usize = 0;
52const FD_SRC: usize = 1;
53const FD_VLAN_TPID: usize = 2;
54const FD_VLAN_PCP: usize = 3;
55const FD_VLAN_DEI: usize = 4;
56const FD_VLAN_ID: usize = 5;
57const FD_ETHERTYPE: usize = 6;
58const FD_LENGTH: usize = 7;
59const FD_LLC_DSAP: usize = 8;
60const FD_LLC_SSAP: usize = 9;
61const FD_LLC_CONTROL: usize = 10;
62
63static FIELD_DESCRIPTORS: &[FieldDescriptor] = &[
64 FieldDescriptor::new("dst", "Destination", FieldType::MacAddr),
65 FieldDescriptor::new("src", "Source", FieldType::MacAddr),
66 FieldDescriptor::new("vlan_tpid", "VLAN TPID", FieldType::U16).optional(),
67 FieldDescriptor::new("vlan_pcp", "VLAN PCP", FieldType::U8).optional(),
68 FieldDescriptor::new("vlan_dei", "VLAN DEI", FieldType::U8).optional(),
69 FieldDescriptor::new("vlan_id", "VLAN ID", FieldType::U16).optional(),
70 FieldDescriptor {
71 name: "ethertype",
72 display_name: "EtherType",
73 field_type: FieldType::U16,
74 optional: true,
75 children: None,
76 display_fn: Some(|v, _siblings| match v {
77 FieldValue::U16(v) => ethertype_name(*v),
78 _ => None,
79 }),
80 format_fn: None,
81 },
82 FieldDescriptor::new("length", "Length", FieldType::U16).optional(),
83 FieldDescriptor::new("llc_dsap", "LLC DSAP", FieldType::U8).optional(),
84 FieldDescriptor::new("llc_ssap", "LLC SSAP", FieldType::U8).optional(),
85 FieldDescriptor::new("llc_control", "LLC Control", FieldType::U8).optional(),
86];
87
88fn ethertype_name(v: u16) -> Option<&'static str> {
90 match v {
91 0x0800 => Some("IPv4"),
92 0x0806 => Some("ARP"),
93 0x8100 => Some("802.1Q"),
94 0x88A8 => Some("802.1ad"),
95 0x86DD => Some("IPv6"),
96 0x8847 => Some("MPLS"),
97 0x8848 => Some("MPLS_MC"),
98 0x8809 => Some("Slow Protocols"),
99 0x88CC => Some("LLDP"),
100 _ => None,
101 }
102}
103
104pub struct EthernetDissector;
106
107impl Dissector for EthernetDissector {
108 fn name(&self) -> &'static str {
109 "Ethernet II"
110 }
111
112 fn short_name(&self) -> &'static str {
113 "Ethernet"
114 }
115
116 fn field_descriptors(&self) -> &'static [FieldDescriptor] {
117 FIELD_DESCRIPTORS
118 }
119
120 fn dissect<'pkt>(
121 &self,
122 data: &'pkt [u8],
123 buf: &mut DissectBuffer<'pkt>,
124 offset: usize,
125 ) -> Result<DissectResult, PacketError> {
126 if data.len() < HEADER_SIZE {
128 return Err(PacketError::Truncated {
129 expected: HEADER_SIZE,
130 actual: data.len(),
131 });
132 }
133
134 let dst = MacAddr([data[0], data[1], data[2], data[3], data[4], data[5]]);
136 let src = MacAddr([data[6], data[7], data[8], data[9], data[10], data[11]]);
138 let ethertype_or_tpid = read_be_u16(data, 12)?;
140
141 let layer_field_start = buf.field_count();
144
145 buf.push_field(
146 &FIELD_DESCRIPTORS[FD_DST],
147 FieldValue::MacAddr(dst),
148 offset..offset + 6,
149 );
150 buf.push_field(
151 &FIELD_DESCRIPTORS[FD_SRC],
152 FieldValue::MacAddr(src),
153 offset + 6..offset + 12,
154 );
155
156 let mut header_len = HEADER_SIZE;
157 let mut current_type = ethertype_or_tpid;
158
159 while current_type == TPID_8021Q || current_type == TPID_8021AD {
164 let vlan_end = header_len + 4;
165 if data.len() < vlan_end {
166 return Err(PacketError::Truncated {
167 expected: vlan_end,
168 actual: data.len(),
169 });
170 }
171
172 let tci = read_be_u16(data, header_len)?;
175 let pcp = (tci >> 13) & 0x07;
176 let dei = (tci >> 12) & 0x01;
177 let vlan_id = tci & 0x0FFF;
178 let inner_type = read_be_u16(data, header_len + 2)?;
179
180 buf.push_field(
181 &FIELD_DESCRIPTORS[FD_VLAN_TPID],
182 FieldValue::U16(current_type),
183 offset + header_len - 2..offset + header_len,
184 );
185 buf.push_field(
186 &FIELD_DESCRIPTORS[FD_VLAN_PCP],
187 FieldValue::U8(pcp as u8),
188 offset + header_len..offset + header_len + 2,
189 );
190 buf.push_field(
191 &FIELD_DESCRIPTORS[FD_VLAN_DEI],
192 FieldValue::U8(dei as u8),
193 offset + header_len..offset + header_len + 2,
194 );
195 buf.push_field(
196 &FIELD_DESCRIPTORS[FD_VLAN_ID],
197 FieldValue::U16(vlan_id),
198 offset + header_len..offset + header_len + 2,
199 );
200
201 header_len = vlan_end;
202 current_type = inner_type;
203 }
204
205 let dispatch_hint = if current_type <= LENGTH_MAX {
206 let llc_start = header_len;
209 let llc_end = llc_start + LLC_HEADER_SIZE;
210 if data.len() < llc_end {
211 return Err(PacketError::Truncated {
212 expected: llc_end,
213 actual: data.len(),
214 });
215 }
216
217 let dsap = data[llc_start];
218 let ssap = data[llc_start + 1];
219 let control = data[llc_start + 2];
220
221 buf.push_field(
222 &FIELD_DESCRIPTORS[FD_LENGTH],
223 FieldValue::U16(current_type),
224 offset + header_len - 2..offset + header_len,
225 );
226 buf.push_field(
227 &FIELD_DESCRIPTORS[FD_LLC_DSAP],
228 FieldValue::U8(dsap),
229 offset + llc_start..offset + llc_start + 1,
230 );
231 buf.push_field(
232 &FIELD_DESCRIPTORS[FD_LLC_SSAP],
233 FieldValue::U8(ssap),
234 offset + llc_start + 1..offset + llc_start + 2,
235 );
236 buf.push_field(
237 &FIELD_DESCRIPTORS[FD_LLC_CONTROL],
238 FieldValue::U8(control),
239 offset + llc_start + 2..offset + llc_end,
240 );
241
242 header_len = llc_end;
243 DispatchHint::ByLlcSap(dsap)
244 } else if current_type < ETHERTYPE_MIN {
245 return Err(PacketError::InvalidFieldValue {
247 field: "type_length",
248 value: current_type as u32,
249 });
250 } else {
251 buf.push_field(
253 &FIELD_DESCRIPTORS[FD_ETHERTYPE],
254 FieldValue::U16(current_type),
255 offset + header_len - 2..offset + header_len,
256 );
257
258 DispatchHint::ByEtherType(current_type)
259 };
260
261 let layer_field_end = buf.field_count();
263 buf.push_layer(packet_dissector_core::packet::Layer {
264 name: self.short_name(),
265 display_name: None,
266 field_descriptors: FIELD_DESCRIPTORS,
267 range: offset..offset + header_len,
268 field_range: layer_field_start..layer_field_end,
269 });
270
271 Ok(DissectResult::new(header_len, dispatch_hint))
272 }
273}