• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /// Produce PCAP Radiotap buffers from Hwsim Frames
16 ///
17 /// This module produces the Radiotap buffers used by PCAP and PcapNG
18 /// for logging 802.11 frames.
19 ///
20 /// See https://www.radiotap.org/
21 use crate::wifi::frame::Frame;
22 use crate::wifi::medium;
23 use crate::wifi::medium::HwsimCmdEnum;
24 use log::info;
25 
26 #[repr(C, packed)]
27 struct RadiotapHeader {
28     version: u8,
29     pad: u8,
30     len: u16,
31     present: u32,
32     channel: ChannelInfo,
33     signal: u8,
34 }
35 
36 #[repr(C)]
37 struct ChannelInfo {
38     freq: u16,
39     flags: u16,
40 }
41 
into_pcap(packet: &[u8]) -> Option<Vec<u8>>42 pub fn into_pcap(packet: &[u8]) -> Option<Vec<u8>> {
43     match medium::parse_hwsim_cmd(packet) {
44         Ok(HwsimCmdEnum::Frame(frame)) => frame_into_pcap(*frame).ok(),
45         Ok(_) => None,
46         Err(e) => {
47             info!("Failed to convert packet to pcap format. Err: {}. Packet: {:?}", e, &packet);
48             None
49         }
50     }
51 }
52 
frame_into_pcap(frame: Frame) -> anyhow::Result<Vec<u8>>53 pub fn frame_into_pcap(frame: Frame) -> anyhow::Result<Vec<u8>> {
54     // Create an instance of the RadiotapHeader with fields for
55     // Channel and Signal.  In the future add more fields from the
56     // Frame.
57 
58     let radiotap_hdr: RadiotapHeader = RadiotapHeader {
59         version: 0,
60         pad: 0,
61         len: (std::mem::size_of::<RadiotapHeader>() as u16),
62         present: (1 << 3 /* channel */ | 1 << 5/* signal dBm */),
63         channel: ChannelInfo { freq: frame.freq.unwrap_or(0) as u16, flags: 0 },
64         signal: frame.signal.unwrap_or(0) as u8,
65     };
66 
67     // Add the struct fields to the buffer manually in little-endian.
68     let mut buffer = Vec::<u8>::new();
69     buffer.push(radiotap_hdr.version);
70     buffer.push(radiotap_hdr.pad);
71     buffer.extend_from_slice(&radiotap_hdr.len.to_le_bytes());
72     buffer.extend_from_slice(&radiotap_hdr.present.to_le_bytes());
73     buffer.extend_from_slice(&radiotap_hdr.channel.freq.to_le_bytes());
74     buffer.extend_from_slice(&radiotap_hdr.channel.flags.to_le_bytes());
75     buffer.push(radiotap_hdr.signal);
76     buffer.extend_from_slice(&frame.data);
77 
78     Ok(buffer)
79 }
80