Skip to content

Commit 6e42eec

Browse files
committed
Create inverse map from layer name to EtherType
This will be used when sculpting to select an EtherType based on the upcoming layer.
1 parent 8111765 commit 6e42eec

File tree

7 files changed

+59
-40
lines changed

7 files changed

+59
-40
lines changed

src/layers/arp.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ pub const ARP_HEADER_LENGTH: usize = 28_usize;
1414

1515
// Register outselves with Ethernet layer
1616
pub(crate) fn register_defaults() -> Result<(), Error> {
17-
ethernet::register_ethertype(ETHERTYPE_ARP, ARP::creator)
17+
let name = ARP::default().name();
18+
ethernet::register_ethertype(ETHERTYPE_ARP, name, ARP::creator)?;
19+
Ok(())
1820
}
1921

2022
/// Structure representing a dissected ARP protocol payload.

src/layers/ethernet/mod.rs

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,23 @@ use crate::{Layer, Packet, ENCAP_TYPE_ETH};
1414

1515
pub const ETH_HEADER_LENGTH: usize = 14_usize;
1616

17+
/// A Map maintaining EtherType -> Creator fns for Layer Creators of L3 Layers.
18+
///
19+
/// The creator function simply creates a `default` L3 struct that implements the dissector
20+
/// for the Layer.
1721
pub fn get_ethertypes_map() -> &'static RwLock<HashMap<EtherType, LayerCreatorFn>> {
18-
/// A Map maintaining EtherType -> Creator fns for Layer Creators of L3 Layers.
19-
///
20-
/// The creator function simply creates a `default` L3 struct that implements the dissector
21-
/// for the Layer.
22-
pub(crate) static ETHERTYPES_MAP: OnceLock<RwLock<HashMap<EtherType, LayerCreatorFn>>> =
23-
OnceLock::new();
22+
static ETHERTYPES_MAP: OnceLock<RwLock<HashMap<EtherType, LayerCreatorFn>>> = OnceLock::new();
2423
ETHERTYPES_MAP.get_or_init(|| RwLock::new(HashMap::new()))
2524
}
2625

26+
/// A Map maintaining String -> EtherType of L3 Layers.
27+
pub fn get_inv_ethertypes_map() -> &'static RwLock<HashMap<String, EtherType>> {
28+
static INV_ETHERTYPES_MAP: OnceLock<RwLock<HashMap<String, EtherType>>> = OnceLock::new();
29+
INV_ETHERTYPES_MAP.get_or_init(|| RwLock::new(HashMap::new()))
30+
}
31+
2732
// Register our Encap Types with the Packet.
2833
pub(crate) fn register_defaults() -> Result<(), Error> {
29-
get_ethertypes_map();
30-
3134
Packet::register_encap_type(ENCAP_TYPE_ETH, Ethernet::creator)
3235
}
3336

@@ -36,12 +39,29 @@ pub(crate) fn register_defaults() -> Result<(), Error> {
3639
/// A Layer that would handle subsequent decoding for a given Ethertype, should register itself
3740
/// by calling this function. For example [`crate::layers::ipv4`] would call `register_ethertype`
3841
/// with [`EtherType`] value of 0x0800, passing the creator function for that layer.
39-
pub fn register_ethertype(eth_type: EtherType, layer: LayerCreatorFn) -> Result<(), Error> {
40-
let mut map = get_ethertypes_map().write().unwrap();
41-
if map.contains_key(&eth_type) {
42-
return Err(Error::RegisterError(format!("ether_type: {}", eth_type)));
42+
pub fn register_ethertype(
43+
eth_type: EtherType,
44+
name: &str,
45+
layer: LayerCreatorFn,
46+
) -> Result<(), Error> {
47+
{
48+
let mut map = get_ethertypes_map().write().unwrap();
49+
if map.contains_key(&eth_type) {
50+
return Err(Error::RegisterError(format!("ether_type: {}", eth_type)));
51+
}
52+
map.insert(eth_type, layer);
53+
}
54+
55+
{
56+
let mut inv_map = get_inv_ethertypes_map().write().unwrap();
57+
if inv_map.contains_key(name) {
58+
return Err(Error::RegisterError(format!(
59+
"Cannot find EtherType for : {}",
60+
name
61+
)));
62+
}
63+
inv_map.insert(name.to_string(), eth_type);
4364
}
44-
map.insert(eth_type, layer);
4565

4666
Ok(())
4767
}
@@ -103,16 +123,15 @@ impl Layer for Ethernet {
103123
result.extend(self.dst_mac.as_slice());
104124
result.extend(self.src_mac.as_slice());
105125

106-
let ethertype: u16 = match info {
107-
"ARP" => crate::types::ETHERTYPE_ARP,
108-
"IPv4" => crate::types::ETHERTYPE_IP,
109-
"IPv6" => crate::types::ETHERTYPE_IP6,
110-
// FIXME: can also be `ETHERTYPE_MPLS_MULTICAST`
111-
"MPLS" => crate::types::ETHERTYPE_MPLS_UNICAST,
112-
"raw" => 0xffff,
113-
// NOTE: should return Err instead
114-
_ => unimplemented!(),
115-
};
126+
let ethertype = get_inv_ethertypes_map()
127+
.read()
128+
.unwrap()
129+
.get(info)
130+
.copied()
131+
.unwrap_or_else(|| match info {
132+
"raw" => crate::types::ETHERTYPE_RAW,
133+
_ => todo!("Return Err here instead"),
134+
});
116135

117136
result.extend(ethertype.to_be_bytes());
118137
result.extend(next_layer.unwrap_or_default());

src/layers/ipv4.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,8 @@ fn get_protocol_map() -> &'static RwLock<HashMap<u8, LayerCreatorFn>> {
3232
// Right now only Ethernet is Supported
3333
pub(crate) fn register_defaults() -> Result<(), Error> {
3434
use crate::layers::ethernet::register_ethertype;
35-
36-
get_protocol_map();
37-
38-
register_ethertype(crate::types::ETHERTYPE_IP, IPv4::creator)?;
39-
35+
let name = IPv4::default().name();
36+
register_ethertype(crate::types::ETHERTYPE_IP, name, IPv4::creator)?;
4037
Ok(())
4138
}
4239

@@ -263,8 +260,8 @@ impl IPv4 {
263260
// 16 bit one's complement of one's complement sum of all 16 bit words
264261
let len = bytes.len();
265262
let mut csum = 0_u32;
266-
for i in 0..len/2 {
267-
let word = u16::from_be_bytes(bytes[2*i..2*(i+1)].try_into().unwrap());
263+
for i in 0..len / 2 {
264+
let word = u16::from_be_bytes(bytes[2 * i..2 * (i + 1)].try_into().unwrap());
268265
csum += word as u32;
269266
}
270267
csum = ((csum >> 16) + (csum & 0xffff)) as u32;
@@ -373,7 +370,7 @@ impl Layer for IPv4 {
373370

374371
let checksum = IPv4::calculate_checksum(&result);
375372
result[checksum_start..checksum_start + 2].copy_from_slice(&checksum.to_be_bytes());
376-
373+
377374
result.extend(next_layer.unwrap_or_default());
378375

379376
Ok(result)

src/layers/ipv6.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use core::convert::TryInto;
44

55
use std::collections::HashMap;
6-
use std::sync::{RwLock,OnceLock};
6+
use std::sync::{OnceLock, RwLock};
77

88
use serde::Serialize;
99

@@ -14,7 +14,6 @@ use crate::Layer;
1414
/// Basic Length of the IPv6 Header
1515
pub const IPV6_BASE_HEADER_LENGTH: usize = 40_usize;
1616

17-
1817
fn get_next_headers_map() -> &'static RwLock<HashMap<u8, LayerCreatorFn>> {
1918
static NEXT_HEADERS_MAP: OnceLock<RwLock<HashMap<u8, LayerCreatorFn>>> = OnceLock::new();
2019
NEXT_HEADERS_MAP.get_or_init(|| RwLock::new(HashMap::new()))
@@ -26,8 +25,8 @@ fn get_next_headers_map() -> &'static RwLock<HashMap<u8, LayerCreatorFn>> {
2625
pub(crate) fn register_defaults() -> Result<(), Error> {
2726
use crate::layers::ethernet::register_ethertype;
2827

29-
get_next_headers_map();
30-
register_ethertype(crate::types::ETHERTYPE_IP6, IPv6::creator)?;
28+
let name = IPv6::default().name();
29+
register_ethertype(crate::types::ETHERTYPE_IP6, name, IPv6::creator)?;
3130

3231
Ok(())
3332
}

src/layers/mpls.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ pub const MPLS_HEADER_LENGTH: usize = 4_usize;
1616

1717
// Register Ourselves to the Ethernet layer, as this is a 2.5 layer protocol
1818
pub(crate) fn register_defaults() -> Result<(), Error> {
19-
ethernet::register_ethertype(ETHERTYPE_MPLS_UNICAST, MPLS::creator)?;
20-
ethernet::register_ethertype(ETHERTYPE_MPLS_MULTICAST, MPLS::creator)
19+
let name = MPLS::default().name();
20+
ethernet::register_ethertype(ETHERTYPE_MPLS_UNICAST, name, MPLS::creator)?;
21+
ethernet::register_ethertype(ETHERTYPE_MPLS_MULTICAST, "[UNKNOWN]", MPLS::creator)?;
22+
Ok(())
2123
}
2224

2325
#[derive(Debug, Default, Serialize, Copy, Clone)]

src/layers/tcp.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
use core::convert::TryInto;
33

44
use std::collections::HashMap;
5-
use std::sync::{RwLock,OnceLock};
5+
use std::sync::{OnceLock, RwLock};
66

77
use serde::Serialize;
88

@@ -12,7 +12,6 @@ use crate::Layer;
1212

1313
use crate::layers::{ipv4, ipv6};
1414

15-
1615
fn get_tcp_apps_map() -> &'static RwLock<HashMap<u16, LayerCreatorFn>> {
1716
static TCP_APPS_MAP: OnceLock<RwLock<HashMap<u16, LayerCreatorFn>>> = OnceLock::new();
1817
TCP_APPS_MAP.get_or_init(|| RwLock::new(HashMap::new()))

src/types/ethertype.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ pub static ETHERTYPE_IP6: EtherType = 0x86dd_u16;
77
pub static ETHERTYPE_ARP: EtherType = 0x0806_u16;
88
pub static ETHERTYPE_MPLS_UNICAST: EtherType = 0x8847_u16;
99
pub static ETHERTYPE_MPLS_MULTICAST: EtherType = 0x8848_u16;
10+
pub static ETHERTYPE_RAW: EtherType = 0xffff_u16;

0 commit comments

Comments
 (0)