1 // Copyright 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 use std::fmt;
16
17 use super::packets::ieee80211::MacAddress;
18 use super::packets::mac80211_hwsim::{self, HwsimAttr, HwsimAttrChild::*, TxRate, TxRateFlag};
19 use super::packets::netlink::NlAttrHdr;
20 use anyhow::{anyhow, Context};
21 use pdl_runtime::Packet;
22 use std::option::Option;
23
24 /// Parse or Build the Hwsim attributes into a set.
25 ///
26 /// Hwsim attributes are used to exchange data between kernel's
27 /// mac80211_hwsim subsystem and a user space process and include:
28 ///
29 /// HWSIM_ATTR_ADDR_TRANSMITTER,
30 /// HWSIM_ATTR_ADDR_RECEIVER,
31 /// HWSIM_ATTR_FRAME,
32 /// HWSIM_ATTR_FLAGS,
33 /// HWSIM_ATTR_RX_RATE,
34 /// HWSIM_ATTR_SIGNAL,
35 /// HWSIM_ATTR_COOKIE,
36 /// HWSIM_ATTR_FREQ (optional)
37 /// HWSIM_ATTR_TX_INFO (new use)
38 /// HWSIM_ATTR_TX_INFO_FLAGS (new use)
39
40 /// Aligns a length to the specified alignment boundary (`NLA_ALIGNTO`).
41 ///
42 /// # Arguments
43 ///
44 /// * `array_length`: The length in bytes to be aligned.
45 ///
46 /// # Returns
47 ///
48 /// * The aligned length, which is a multiple of `NLA_ALIGNTO`.
49 ///
nla_align(array_length: usize) -> usize50 fn nla_align(array_length: usize) -> usize {
51 const NLA_ALIGNTO: usize = 4;
52 array_length.wrapping_add(NLA_ALIGNTO - 1) & !(NLA_ALIGNTO - 1)
53 }
54
55 #[derive(Default)]
56 pub struct HwsimAttrSetBuilder {
57 transmitter: Option<MacAddress>,
58 receiver: Option<MacAddress>,
59 frame: Option<Vec<u8>>,
60 flags: Option<u32>,
61 rx_rate_idx: Option<u32>,
62 signal: Option<u32>,
63 cookie: Option<u64>,
64 freq: Option<u32>,
65 tx_info: Option<Vec<TxRate>>,
66 tx_info_flags: Option<Vec<TxRateFlag>>,
67 attributes: Vec<u8>,
68 }
69
70 #[derive(Debug)]
71 pub struct HwsimAttrSet {
72 pub transmitter: Option<MacAddress>,
73 pub receiver: Option<MacAddress>,
74 pub frame: Option<Vec<u8>>,
75 pub flags: Option<u32>,
76 pub rx_rate_idx: Option<u32>,
77 pub signal: Option<u32>,
78 pub cookie: Option<u64>,
79 pub freq: Option<u32>,
80 pub tx_info: Option<Vec<TxRate>>,
81 pub tx_info_flags: Option<Vec<TxRateFlag>>,
82 pub attributes: Vec<u8>,
83 }
84
85 /// Builder pattern for each of the HWSIM_ATTR used in conjunction
86 /// with the HwsimAttr packet formats defined in `mac80211_hwsim.pdl`
87 ///
88 /// Used during `parse` or to create new HwsimCmd packets containing
89 /// an attributes vector.
90 ///
91 /// The attributes field will contain the raw bytes in NLA format
92 /// in the order of method calls.
93 impl HwsimAttrSetBuilder {
94 // Add packet to the attributes vec and pad for proper NLA
95 // alignment. This provides for to_bytes for a HwsimMsg for
96 // packets constructed by the Builder.
97
extend_attributes<P: Packet>(&mut self, packet: P)98 fn extend_attributes<P: Packet>(&mut self, packet: P) {
99 let mut vec: Vec<u8> = packet.encode_to_vec().unwrap();
100 let nla_padding = nla_align(vec.len()) - vec.len();
101 vec.extend(vec![0; nla_padding]);
102 self.attributes.extend(vec);
103 }
104
transmitter(&mut self, transmitter: &[u8; 6]) -> &mut Self105 pub fn transmitter(&mut self, transmitter: &[u8; 6]) -> &mut Self {
106 self.extend_attributes(mac80211_hwsim::HwsimAttrAddrTransmitter {
107 address: *transmitter,
108 nla_m: 0,
109 nla_o: 0,
110 });
111 self.transmitter = Some(MacAddress::from(transmitter));
112 self
113 }
114
receiver(&mut self, receiver: &[u8; 6]) -> &mut Self115 pub fn receiver(&mut self, receiver: &[u8; 6]) -> &mut Self {
116 self.extend_attributes(mac80211_hwsim::HwsimAttrAddrReceiver {
117 address: *receiver,
118 nla_m: 0,
119 nla_o: 0,
120 });
121 self.receiver = Some(MacAddress::from(receiver));
122 self
123 }
124
frame(&mut self, frame: &[u8]) -> &mut Self125 pub fn frame(&mut self, frame: &[u8]) -> &mut Self {
126 self.extend_attributes(mac80211_hwsim::HwsimAttrFrame {
127 data: (*frame).to_vec(),
128 nla_m: 0,
129 nla_o: 0,
130 });
131 self.frame = Some(frame.to_vec());
132 self
133 }
134
flags(&mut self, flags: u32) -> &mut Self135 pub fn flags(&mut self, flags: u32) -> &mut Self {
136 self.extend_attributes(mac80211_hwsim::HwsimAttrFlags { flags, nla_m: 0, nla_o: 0 });
137 self.flags = Some(flags);
138 self
139 }
140
rx_rate(&mut self, rx_rate_idx: u32) -> &mut Self141 pub fn rx_rate(&mut self, rx_rate_idx: u32) -> &mut Self {
142 self.extend_attributes(mac80211_hwsim::HwsimAttrRxRate { rx_rate_idx, nla_m: 0, nla_o: 0 });
143 self.rx_rate_idx = Some(rx_rate_idx);
144 self
145 }
146
signal(&mut self, signal: u32) -> &mut Self147 pub fn signal(&mut self, signal: u32) -> &mut Self {
148 self.extend_attributes(mac80211_hwsim::HwsimAttrSignal { signal, nla_m: 0, nla_o: 0 });
149 self.signal = Some(signal);
150 self
151 }
152
cookie(&mut self, cookie: u64) -> &mut Self153 pub fn cookie(&mut self, cookie: u64) -> &mut Self {
154 self.extend_attributes(mac80211_hwsim::HwsimAttrCookie { cookie, nla_m: 0, nla_o: 0 });
155 self.cookie = Some(cookie);
156 self
157 }
158
freq(&mut self, freq: u32) -> &mut Self159 pub fn freq(&mut self, freq: u32) -> &mut Self {
160 self.extend_attributes(mac80211_hwsim::HwsimAttrFreq { freq, nla_m: 0, nla_o: 0 });
161 self.freq = Some(freq);
162 self
163 }
164
tx_info(&mut self, tx_info: &[TxRate]) -> &mut Self165 pub fn tx_info(&mut self, tx_info: &[TxRate]) -> &mut Self {
166 self.extend_attributes(mac80211_hwsim::HwsimAttrTxInfo {
167 tx_rates: (*tx_info).to_vec(),
168 nla_m: 0,
169 nla_o: 0,
170 });
171 self.tx_info = Some(tx_info.to_vec());
172 self
173 }
174
tx_info_flags(&mut self, tx_rate_flags: &[TxRateFlag]) -> &mut Self175 pub fn tx_info_flags(&mut self, tx_rate_flags: &[TxRateFlag]) -> &mut Self {
176 self.extend_attributes(mac80211_hwsim::HwsimAttrTxInfoFlags {
177 tx_rate_flags: (*tx_rate_flags).to_vec(),
178 nla_m: 0,
179 nla_o: 0,
180 });
181 self.tx_info_flags = Some(tx_rate_flags.to_vec());
182 self
183 }
184
build(self) -> anyhow::Result<HwsimAttrSet>185 pub fn build(self) -> anyhow::Result<HwsimAttrSet> {
186 Ok(HwsimAttrSet {
187 transmitter: self.transmitter,
188 receiver: self.receiver,
189 cookie: self.cookie,
190 flags: self.flags,
191 rx_rate_idx: self.rx_rate_idx,
192 signal: self.signal,
193 frame: self.frame,
194 freq: self.freq,
195 tx_info: self.tx_info,
196 tx_info_flags: self.tx_info_flags,
197 attributes: self.attributes,
198 })
199 }
200 }
201
202 impl fmt::Display for HwsimAttrSet {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204 write!(f, "{{ ")?;
205 self.transmitter.map(|v| write!(f, "transmitter: {}, ", v));
206 self.receiver.map(|v| write!(f, "receiver: {}, ", v));
207 self.cookie.map(|v| write!(f, "cookie: {}, ", v));
208 self.flags.map(|v| write!(f, "flags: {}, ", v));
209 self.rx_rate_idx.map(|v| write!(f, "rx_rate_idx: {}, ", v));
210 self.signal.map(|v| write!(f, "signal: {}, ", v));
211 self.frame.as_ref().map(|v| write!(f, "frame: {:?}, ", &v));
212 self.freq.map(|v| write!(f, "freq: {}, ", v));
213 self.tx_info.as_ref().map(|v| write!(f, "tx_info: {:?}, ", &v));
214 self.tx_info_flags.as_ref().map(|v| write!(f, "tx_info_flags: {:?}, ", &v));
215 write!(f, "}}")?;
216 Ok(())
217 }
218 }
219
220 impl HwsimAttrSet {
221 /// Creates a new `HwsimAttrSetBuilder` with default settings, ready for configuring attributes.
222 ///
223 /// # Returns
224 ///
225 /// * A new `HwsimAttrSetBuilder` instance, initialized with default values.
226 ///
227 /// # Examples
228 ///
229 /// ```rust
230 /// let mut builder = HwsimAttrSetBuilder::builder();
231 /// builder.signal(42).cookie(32); // Example attribute configuration
232 /// let attr_set = builder.build();
233 /// ```
builder() -> HwsimAttrSetBuilder234 pub fn builder() -> HwsimAttrSetBuilder {
235 HwsimAttrSetBuilder::default()
236 }
237
238 /// Parse and validates the attributes from a HwsimMsg command.
parse(attributes: &[u8]) -> anyhow::Result<HwsimAttrSet>239 pub fn parse(attributes: &[u8]) -> anyhow::Result<HwsimAttrSet> {
240 Self::parse_with_frame_transmitter(attributes, Option::None, Option::None)
241 }
242 /// Parse and validates the attributes from a HwsimMsg command.
243 /// Update frame and transmitter if provided.
parse_with_frame_transmitter( attributes: &[u8], frame: Option<&[u8]>, transmitter: Option<&[u8; 6]>, ) -> anyhow::Result<HwsimAttrSet>244 pub fn parse_with_frame_transmitter(
245 attributes: &[u8],
246 frame: Option<&[u8]>,
247 transmitter: Option<&[u8; 6]>,
248 ) -> anyhow::Result<HwsimAttrSet> {
249 let mut index: usize = 0;
250 let mut builder = HwsimAttrSet::builder();
251 while index < attributes.len() {
252 // Parse a generic netlink attribute to get the size
253 let nla_hdr =
254 NlAttrHdr::decode_full(&attributes[index..index + 4]).context("NlAttrHdr")?;
255 let nla_len = nla_hdr.nla_len as usize;
256 // Now parse a single attribute at a time from the
257 // attributes to allow padding per attribute.
258 let hwsim_attr = HwsimAttr::decode_full(&attributes[index..index + nla_len])?;
259 match hwsim_attr.specialize().context("HwsimAttr")? {
260 HwsimAttrAddrTransmitter(child) => {
261 builder.transmitter(transmitter.unwrap_or(child.address()))
262 }
263 HwsimAttrAddrReceiver(child) => builder.receiver(&child.address),
264 HwsimAttrFrame(child) => builder.frame(frame.unwrap_or(&child.data)),
265 HwsimAttrFlags(child) => builder.flags(child.flags),
266 HwsimAttrRxRate(child) => builder.rx_rate(child.rx_rate_idx),
267 HwsimAttrSignal(child) => builder.signal(child.signal),
268 HwsimAttrCookie(child) => builder.cookie(child.cookie),
269 HwsimAttrFreq(child) => builder.freq(child.freq),
270 HwsimAttrTxInfo(child) => builder.tx_info(&child.tx_rates),
271 HwsimAttrTxInfoFlags(child) => builder.tx_info_flags(&child.tx_rate_flags),
272 _ => {
273 return Err(anyhow!(
274 "Invalid attribute message: {:?}",
275 hwsim_attr.nla_type as u32
276 ))
277 }
278 };
279 // Manually step through the attribute bytes aligning as
280 // we go because netlink aligns each attribute which isn't
281 // a feature of PDL parser.
282 index += nla_align(nla_len);
283 }
284 builder.build()
285 }
286 }
287
288 #[cfg(test)]
289 mod tests {
290 use super::*;
291 use crate::wifi::packets::ieee80211::parse_mac_address;
292 use crate::wifi::packets::mac80211_hwsim::{HwsimCmd, HwsimMsg};
293 use anyhow::Context;
294 use anyhow::Error;
295
296 // Validate `HwsimAttrSet` attribute parsing from byte vector.
297 #[test]
test_attr_set_parse()298 fn test_attr_set_parse() {
299 let packet: Vec<u8> = include!("test_packets/hwsim_cmd_frame.csv");
300 let hwsim_msg = HwsimMsg::decode_full(&packet).unwrap();
301 assert_eq!(hwsim_msg.hwsim_hdr().hwsim_cmd, HwsimCmd::Frame);
302 let attrs = HwsimAttrSet::parse(hwsim_msg.attributes()).unwrap();
303
304 // Validate each attribute parsed
305 assert_eq!(attrs.transmitter, MacAddress::try_from(11670786u64).ok());
306 assert!(attrs.receiver.is_none());
307 assert!(attrs.frame.is_some());
308 assert_eq!(attrs.flags, Some(2));
309 assert!(attrs.rx_rate_idx.is_none());
310 assert!(attrs.signal.is_none());
311 assert_eq!(attrs.cookie, Some(201));
312 assert_eq!(attrs.freq, Some(2422));
313 assert!(attrs.tx_info.is_some());
314 }
315
316 // Validate the contents of the `attributes` bytes constructed by
317 // the Builder by matching with the bytes containing the input
318 // attributes. Confirms attribute order, packet format and
319 // padding.
320 #[test]
test_attr_set_attributes()321 fn test_attr_set_attributes() {
322 let packet: Vec<u8> = include!("test_packets/hwsim_cmd_frame.csv");
323 let hwsim_msg = HwsimMsg::decode_full(&packet).unwrap();
324 assert_eq!(hwsim_msg.hwsim_hdr().hwsim_cmd, HwsimCmd::Frame);
325 let attrs = HwsimAttrSet::parse(hwsim_msg.attributes()).unwrap();
326 assert_eq!(&attrs.attributes, hwsim_msg.attributes());
327 }
328
329 /// Validate changing frame and transmitter during the parse.
330 /// 1. Check if reinserting the same values results in identical bytes.
331 /// 2. Insert modified values, parse to bytes, and parse back again to check
332 /// if the round trip values are identical.
333 #[test]
test_attr_set_parse_with_frame_transmitter() -> Result<(), Error>334 fn test_attr_set_parse_with_frame_transmitter() -> Result<(), Error> {
335 let packet: Vec<u8> = include!("test_packets/hwsim_cmd_frame.csv");
336 let hwsim_msg = HwsimMsg::decode_full(&packet)?;
337 assert_eq!(hwsim_msg.hwsim_hdr().hwsim_cmd, HwsimCmd::Frame);
338 let attrs = HwsimAttrSet::parse(hwsim_msg.attributes())?;
339 let transmitter: [u8; 6] = attrs.transmitter.context("transmitter")?.into();
340 let mod_attrs = HwsimAttrSet::parse_with_frame_transmitter(
341 hwsim_msg.attributes(),
342 attrs.frame.as_deref(),
343 Some(&transmitter),
344 )?;
345
346 assert_eq!(attrs.attributes, mod_attrs.attributes);
347
348 // Change frame and transmitter.
349 let mod_frame = Some(vec![0, 1, 2, 3]);
350 let mod_transmitter: Option<[u8; 6]> =
351 Some(parse_mac_address("00:0b:85:71:20:ce").context("transmitter")?.into());
352
353 let mod_attrs = HwsimAttrSet::parse_with_frame_transmitter(
354 &attrs.attributes,
355 mod_frame.as_deref(),
356 mod_transmitter.as_ref(),
357 )?;
358
359 let parsed_attrs = HwsimAttrSet::parse(&mod_attrs.attributes)?;
360 assert_eq!(parsed_attrs.transmitter, mod_transmitter.map(|t| MacAddress::from(&t)));
361 assert_eq!(parsed_attrs.frame, mod_frame);
362 Ok(())
363 }
364
365 #[test]
test_hwsim_attr_set_display()366 fn test_hwsim_attr_set_display() {
367 let packet: Vec<u8> = include!("test_packets/hwsim_cmd_frame.csv");
368 let hwsim_msg = HwsimMsg::decode_full(&packet).unwrap();
369 let attrs = HwsimAttrSet::parse(hwsim_msg.attributes()).unwrap();
370
371 let fmt_attrs = format!("{}", attrs);
372 assert!(fmt_attrs.contains("transmitter: 02:15:b2:00:00:00"));
373 assert!(fmt_attrs.contains("cookie: 201"));
374 }
375 }
376