blob: 50b4cf5819adbbab8f33ce89990c6fe1f9007bde [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use fidl_fuchsia_inspect as fidl_inspect;
use std::fmt::Display;
use wlan_inspect::nodes::{BoundedListNode, NodeExt, SharedNodePtr};
use wlan_rsn::rsna::SecAssocUpdate;
/// These limits are set to capture roughly 5 to 10 recent connection attempts. An average
/// successful connection attempt would generate about 5 state events and 7 supplicant events (this
/// number may be different in error cases).
const STATE_EVENTS_LIMIT: usize = 50;
const SUPPLICANT_EVENTS_LIMIT: usize = 50;
/// Limit set to capture roughly join scans for 10 recent connection attempts.
const JOIN_SCAN_EVENTS_LIMIT: usize = 10;
/// Wrapper struct SME inspection nodes
pub struct SmeNode {
/// Inspection node to log recent state transitions, or cases where an event would that would
/// normally cause a state transition doesn't due to an error.
states: BoundedListNode,
/// Inspection node to log EAPOL frames processed by supplicant and its output.
supplicant_events: BoundedListNode,
/// Inspection node to log recent join scan results.
pub join_scan_events: BoundedListNode,
}
impl SmeNode {
pub fn new(node: SharedNodePtr) -> Self {
let mut node = node.lock();
let states = BoundedListNode::new(node.create_child("states"), STATE_EVENTS_LIMIT);
let supplicant_events =
BoundedListNode::new(node.create_child("supplicant_events"), SUPPLICANT_EVENTS_LIMIT);
let join_scan_events =
BoundedListNode::new(node.create_child("join_scan_events"), JOIN_SCAN_EVENTS_LIMIT);
Self { states, supplicant_events, join_scan_events }
}
pub fn log_state_change<F, T, C>(&mut self, from: F, to: T, cause: Option<C>)
where
F: Display,
T: Display,
C: Display,
{
let msg = match cause {
None => format!("{} -> {}", from, to),
Some(cause) => format!("{} -> {} (why={})", from, to, cause),
};
let node = self.states.request_entry();
node.lock().set_time().insert_str("msg", msg);
}
pub fn log_eapol_frame(
&mut self,
eapol_pdu: Vec<u8>,
transmit_direction: TransmitDirection,
) -> SharedNodePtr {
let key = match transmit_direction {
TransmitDirection::Rx => "rx_eapol_frame",
TransmitDirection::Tx => "tx_eapol_frame",
};
let node = self.supplicant_events.request_entry();
node.lock().set_time().add_property(fidl_inspect::Property {
key: key.to_string(),
value: fidl_inspect::PropertyValue::Bytes(eapol_pdu),
});
node
}
pub fn log_supplicant_update(&mut self, update: &SecAssocUpdate) {
match update {
SecAssocUpdate::TxEapolKeyFrame(_) => (), // log separately
SecAssocUpdate::Key(key) => {
let node = self.supplicant_events.request_entry();
node.lock().set_time().insert_str("derived_key", key.name());
}
SecAssocUpdate::Status(status) => {
let node = self.supplicant_events.request_entry();
node.lock().set_time().insert_debug("rsna_status", status);
}
}
}
}
pub enum TransmitDirection {
Rx,
Tx,
}