Skip to content

Commit d81cb85

Browse files
committed
add(dot15d4-cat): print the structure of a frame
1 parent 10273e0 commit d81cb85

File tree

2 files changed

+214
-0
lines changed

2 files changed

+214
-0
lines changed

dot15d4/Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,19 @@ bitflags = "2.4.2"
1313
heapless = "0.8.0"
1414
critical-section = "1.1"
1515

16+
colored = { version = "2", optional = true }
17+
clap = { version = "4.5.1", features = ["derive"], optional = true }
18+
hex = { version = "0.4.3", optional = true }
19+
1620
[dev-dependencies]
1721
tracing-subscriber = "0.3"
1822
critical-section = { version = "1.1", features = ["std"] }
1923

2024
[features]
2125
std = []
2226
default = ["std"]
27+
dot15d4-cat = ["std", "colored", "clap", "hex"]
28+
29+
[[bin]]
30+
name = "dot15d4-cat"
31+
required-features = ["dot15d4-cat"]

dot15d4/src/bin/dot15d4-cat.rs

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
use clap::Parser;
2+
use colored::*;
3+
use dot15d4::frame::*;
4+
5+
/// `cat` for IEEE 802.15.4 frames.
6+
#[derive(Parser, Debug)]
7+
#[command(version, about, long_about = None)]
8+
struct Args {
9+
/// The IEEE 802.15.4 frame to parse.
10+
input: String,
11+
}
12+
13+
fn main() {
14+
let args = Args::parse();
15+
let data = hex::decode(args.input).unwrap();
16+
let frame = Frame::new(&data[..]).unwrap();
17+
18+
let fc = frame.frame_control();
19+
println!("{}", "Frame Control".underline().bold());
20+
println!(
21+
" {}: {}{:?}",
22+
"frame type".bold(),
23+
if fc.frame_version() == FrameVersion::Ieee802154_2020
24+
&& fc.frame_type() == FrameType::Beacon
25+
{
26+
"Enhanced "
27+
} else {
28+
""
29+
},
30+
fc.frame_type()
31+
);
32+
println!(
33+
" {}: {}",
34+
"security".bold(),
35+
fc.security_enabled() as usize
36+
);
37+
println!(
38+
" {}: {}",
39+
"frame pending".bold(),
40+
fc.frame_pending() as usize
41+
);
42+
println!(" {}: {}", "ack request".bold(), fc.ack_request() as usize);
43+
println!(
44+
" {}: {}",
45+
"pan id compression".bold(),
46+
fc.pan_id_compression() as usize
47+
);
48+
println!(
49+
" {}: {}",
50+
"sequence number suppression".bold(),
51+
fc.sequence_number_suppression() as usize
52+
);
53+
println!(
54+
" {}: {}",
55+
"information elements present".bold(),
56+
fc.information_elements_present() as usize
57+
);
58+
println!(
59+
" {}: {:?}",
60+
"dst addressing mode".bold(),
61+
fc.dst_addressing_mode()
62+
);
63+
println!(
64+
" {}: {:?}",
65+
"src addressing mode".bold(),
66+
fc.src_addressing_mode()
67+
);
68+
println!(
69+
" {}: {} ({:?})",
70+
"frame version".bold(),
71+
fc.frame_version() as usize,
72+
fc.frame_version()
73+
);
74+
75+
if let Some(seq) = frame.sequence_number() {
76+
println!("{}", "Sequence Number".underline().bold());
77+
println!(" {}: {}", "sequence number".bold(), seq);
78+
}
79+
80+
if let Some(addr) = frame.addressing() {
81+
println!("{}", "Addressing".underline().bold());
82+
83+
if let Some(dst_pan_id) = addr.dst_pan_id(&fc) {
84+
println!(" {}: {:x}", "dst pan id".bold(), dst_pan_id);
85+
}
86+
87+
if let Some(dst_addr) = addr.dst_address(&fc) {
88+
println!(
89+
" {}: {}{}",
90+
"dst addr".bold(),
91+
dst_addr,
92+
if dst_addr.is_broadcast() {
93+
" (broadcast)"
94+
} else {
95+
""
96+
}
97+
);
98+
}
99+
100+
if let Some(src_pan_id) = addr.src_pan_id(&fc) {
101+
println!(" {}: {:x}", "src pan id".bold(), src_pan_id);
102+
}
103+
104+
if let Some(src_addr) = addr.src_address(&fc) {
105+
println!(
106+
" {}: {}{}",
107+
"src addr".bold(),
108+
src_addr,
109+
if src_addr.is_broadcast() {
110+
" (broadcast)"
111+
} else {
112+
""
113+
}
114+
);
115+
}
116+
117+
if let Some(_) = frame.auxiliary_security_header() {
118+
println!("{}", "Auxiliary Security Header".underline().bold());
119+
println!(" unimplementec");
120+
}
121+
122+
if let Some(ie) = frame.information_elements() {
123+
println!("{}", "Information Elements".underline().bold());
124+
125+
let headers: Vec<HeaderInformationElement<&[u8]>> =
126+
ie.header_information_elements().collect();
127+
if !headers.is_empty() {
128+
println!(" {}", "Header Information Elements".italic());
129+
130+
for header in headers {
131+
let id = header.element_id();
132+
if matches!(
133+
id,
134+
HeaderElementId::HeaderTermination1 | HeaderElementId::HeaderTermination2
135+
) {
136+
println!(" {}", format!("{:?}", header.element_id()).bold());
137+
} else {
138+
println!(" {}", format!("{:?}", header.element_id()).bold(),);
139+
140+
match id {
141+
HeaderElementId::TimeCorrection => {
142+
println!(" {}", TimeCorrection::new(header.content()));
143+
}
144+
_ => println!(" unimplemented"),
145+
}
146+
}
147+
}
148+
}
149+
150+
let payloads: Vec<PayloadInformationElement<&[u8]>> =
151+
ie.payload_information_elements().collect();
152+
if !payloads.is_empty() {
153+
println!(" {}", "Payload Information Elements".italic());
154+
155+
for payload in payloads {
156+
match payload.group_id() {
157+
PayloadGroupId::Mlme => {
158+
println!(" {}", "Mlme");
159+
for nested in payload.nested_information_elements() {
160+
println!(
161+
" {}",
162+
match nested.sub_id() {
163+
NestedSubId::Short(id) => format!("{:?}", id).bold(),
164+
NestedSubId::Long(id) => format!("{:?}", id).bold(),
165+
}
166+
);
167+
168+
match nested.sub_id() {
169+
NestedSubId::Short(NestedSubIdShort::TschSynchronization) => {
170+
println!(
171+
" {}",
172+
TschSynchronization::new(nested.content())
173+
);
174+
}
175+
NestedSubId::Short(NestedSubIdShort::TschTimeslot) => {
176+
println!(" {}", TschTimeslot::new(nested.content()));
177+
}
178+
NestedSubId::Short(NestedSubIdShort::TschSlotframeAndLink) => {
179+
println!(
180+
" {}",
181+
TschSlotframeAndLink::new(nested.content())
182+
);
183+
}
184+
NestedSubId::Long(NestedSubIdLong::ChannelHopping) => {
185+
println!(
186+
" {}",
187+
ChannelHopping::new(nested.content())
188+
);
189+
}
190+
_ => println!(" unimplemented"),
191+
}
192+
}
193+
}
194+
id => println!(" {}: unimplemented", format!("{:?}", id).bold()),
195+
}
196+
}
197+
}
198+
}
199+
200+
if let Some(payload) = frame.payload() {
201+
println!("{}", "Payload".underline().bold());
202+
println!(" {:x?}", payload);
203+
}
204+
}
205+
}

0 commit comments

Comments
 (0)