Skip to content

Architecture

whisprer edited this page Nov 18, 2025 · 1 revision

Architecture

This document describes the architectural design of Zigbee Analyzer, including the crate structure, core abstractions, and data flow.

Design Philosophy

Zigbee Analyzer is built on these core principles:

  1. Modularity: Clean separation between hardware, protocol, and UI layers
  2. Extensibility: Easy to add new hardware drivers and analysis modules
  3. Performance: Zero-copy where possible, async/await for concurrency
  4. Type Safety: Leverage Rust's type system for protocol correctness
  5. Hardware Abstraction: Uniform API across different Zigbee adapters

Crate Structure

The project is organized as a Cargo workspace with the following crates:

zigbee-analyzer/
├── zigbee-core/        # Core packet structures and parsing
├── zigbee-hal/         # Hardware abstraction layer
├── zigbee-drivers/     # Hardware-specific drivers
├── zigbee-analysis/    # Analysis and pattern recognition
├── zigbee-crypto/      # Cryptographic operations
├── zigbee-storage/     # Database and persistence
└── zigbee-ui/          # User interface (TUI)

Dependency Graph

┌─────────────┐
│ zigbee-ui   │
└──────┬──────┘
       │
       ├──────────┬──────────┬──────────┐
       │          │          │          │
       v          v          v          v
┌──────────┐ ┌──────────┐ ┌────────┐ ┌─────────┐
│ drivers  │ │ analysis │ │ crypto │ │ storage │
└────┬─────┘ └────┬─────┘ └───┬────┘ └────┬────┘
     │            │            │           │
     v            v            v           v
┌─────────┐  ┌──────────────────────────────┐
│   hal   │  │         zigbee-core          │
└────┬────┘  └──────────────────────────────┘
     │                     │
     └─────────────────────┘

Core Crates

zigbee-core

Purpose: Foundation for all Zigbee protocol handling.

Key Components:

// Packet structures
pub struct RawPacket {
    pub timestamp: SystemTime,
    pub channel: u8,
    pub rssi: i8,
    pub lqi: u8,
    pub data: Vec<u8>,
}

pub struct ParsedPacket {
    pub mac: MacFrame,
    pub network: Option<NetworkFrame>,
    pub aps: Option<ApsFrame>,
    pub zcl: Option<ZclFrame>,
}

// Layer parsing
pub trait PacketParser {
    fn parse(&self, data: &[u8]) -> Result<Self, ParseError>;
}

Responsibilities:

  • IEEE 802.15.4 MAC frame parsing
  • Zigbee Network Layer (NWK) parsing
  • Application Support Sublayer (APS) parsing
  • Zigbee Cluster Library (ZCL) parsing
  • Frame validation and checksum verification

Dependencies: None (leaf crate)


zigbee-hal

Purpose: Hardware abstraction layer providing a uniform interface to all Zigbee adapters.

Key Traits:

/// Core capture interface
#[async_trait]
pub trait ZigbeeCapture: Send + Sync {
    async fn initialize(&mut self) -> HalResult<()>;
    async fn set_channel(&mut self, channel: u8) -> HalResult<()>;
    async fn capture_packet(&mut self) -> HalResult<RawPacket>;
    fn capabilities(&self) -> &DeviceCapabilities;
    async fn shutdown(&mut self) -> HalResult<()>;
}

/// Advanced features (optional)
#[async_trait]
pub trait PacketInjection: ZigbeeCapture {
    async fn inject_packet(&mut self, packet: &RawPacket) -> HalResult<()>;
    async fn set_tx_power(&mut self, dbm: i8) -> HalResult<()>;
}

Device Capabilities:

pub struct DeviceCapabilities {
    pub packet_injection: bool,
    pub promiscuous_mode: bool,
    pub supported_channels: Vec<u8>,
    pub max_sample_rate: u32,
    pub hardware_filtering: bool,
}

Responsibilities:

  • Define hardware abstraction traits
  • Capability discovery
  • Error types and result handling
  • Async interface for I/O operations

Dependencies: zigbee-core, async-trait, thiserror


zigbee-drivers

Purpose: Concrete implementations of hardware drivers.

Supported Drivers:

pub mod ti_cc2531;      // TI CC2531 USB dongle
pub mod ti_cc2652;      // TI CC2652R/P dongles
pub mod registry;       // Auto-detection and driver registry
pub mod pcap;           // PCAP file reader/writer

Driver Registry:

pub struct DriverRegistry {
    drivers: Vec<DriverInfo>,
}

impl DriverRegistry {
    pub fn new() -> Self;
    pub fn detect_devices(&self) -> Vec<DetectedDevice>;
    pub fn create_driver(&self, device: &DetectedDevice) 
        -> Option<Box<dyn ZigbeeCapture>>;
}

Example: CC2531 Driver Structure:

pub struct CC2531 {
    port: Option<Box<dyn SerialPort>>,
    port_name: String,
    channel: u8,
    active: bool,
    capabilities: DeviceCapabilities,
    buffer: VecDeque<RawPacket>,
}

// Protocol constants
const SOF: u8 = 0xFE;           // Start of Frame
const CMD_START: u8 = 0x22;     // Start capture
const CMD_STOP: u8 = 0x23;      // Stop capture
const CMD_SET_CHANNEL: u8 = 0x24;  // Set channel

Responsibilities:

  • Device-specific protocol implementation
  • USB/serial communication
  • Buffer management
  • Error recovery and device reset

Dependencies: zigbee-hal, zigbee-core, serialport, rusb


zigbee-analysis

Purpose: High-level analysis of captured traffic.

Modules:

pub mod topology;       // Network topology mapping
pub mod patterns;       // Traffic pattern detection
pub mod security;       // Cryptographic analysis
pub mod statistics;     // Statistical analysis

Key Features:

Network Topology:

pub struct NetworkTopology {
    coordinator: Option<Device>,
    routers: HashMap<u16, Device>,
    end_devices: HashMap<u16, Device>,
    links: Vec<Link>,
}

impl NetworkTopology {
    pub fn from_packets(&mut self, packets: &[ParsedPacket]);
    pub fn visualize(&self) -> String;
    pub fn export_graphviz(&self) -> String;
}

Pattern Detection:

pub struct PatternDetector {
    pub fn detect_join_sequences(&self) -> Vec<JoinSequence>;
    pub fn detect_periodic_beacons(&self) -> Vec<BeaconPattern>;
    pub fn detect_key_exchange(&self) -> Vec<KeyExchange>;
}

Responsibilities:

  • Device discovery and tracking
  • Network graph construction
  • Communication pattern analysis
  • Anomaly detection

Dependencies: zigbee-core, petgraph (for graphs)


zigbee-crypto

Purpose: Cryptographic operations for Zigbee security.

Modules:

pub mod aes_ccm;        // AES-CCM* encryption/decryption
pub mod keys;           // Key management
pub mod nonce;          // Nonce generation and validation

Key Types:

pub enum ZigbeeKey {
    NetworkKey([u8; 16]),
    LinkKey([u8; 16]),
    TrustCenterLinkKey([u8; 16]),
}

pub struct SecurityMaterial {
    pub network_key: Option<ZigbeeKey>,
    pub link_keys: HashMap<u64, ZigbeeKey>,
}

impl SecurityMaterial {
    pub fn decrypt_packet(&self, packet: &ParsedPacket) 
        -> Result<Vec<u8>, CryptoError>;
}

Responsibilities:

  • AES-CCM* cipher implementation
  • Key derivation and management
  • Nonce construction
  • Packet encryption/decryption

Dependencies: zigbee-core, aes, ccm


zigbee-storage

Purpose: Persistent storage for captures and analysis.

Schema:

pub struct CaptureDatabase {
    conn: Connection,
}

// Tables:
// - captures: Capture sessions
// - packets: Raw packet data
// - devices: Discovered devices
// - networks: Network metadata

API:

impl CaptureDatabase {
    pub fn new(path: &str) -> Result<Self>;
    pub fn save_packet(&mut self, packet: &RawPacket) -> Result<i64>;
    pub fn save_device(&mut self, device: &Device) -> Result<()>;
    pub fn query_packets(&self, filter: PacketFilter) 
        -> Result<Vec<RawPacket>>;
}

Responsibilities:

  • SQLite database management
  • Capture session tracking
  • Query interface for analysis
  • Export to various formats (PCAP, JSON, CSV)

Dependencies: zigbee-core, rusqlite


zigbee-ui

Purpose: Terminal-based user interface.

Architecture:

pub struct App {
    // State
    device: Option<Arc<Mutex<Box<dyn ZigbeeCapture>>>>,
    topology: NetworkTopology,
    packets: VecDeque<ParsedPacket>,
    
    // UI State
    current_view: ViewType,
    selected_channel: u8,
    is_capturing: bool,
}

pub enum ViewType {
    Capture,        // Live packet list
    Topology,       // Network graph
    DeviceDetail,   // Device information
    Analysis,       // Statistics and patterns
    Settings,       // Configuration
}

Event Loop:

loop {
    // Handle input events
    if event::poll(Duration::from_millis(100))? {
        match event::read()? {
            Event::Key(key) => handle_key(key),
            _ => {}
        }
    }
    
    // Capture packets (non-blocking)
    if let Some(packet) = try_capture_packet().await {
        process_packet(packet);
    }
    
    // Render UI
    terminal.draw(|f| render_ui(f, &app))?;
}

Responsibilities:

  • Interactive terminal UI (using ratatui)
  • Real-time packet display
  • Network visualization
  • Configuration management

Dependencies: zigbee-analysis, zigbee-drivers, ratatui, crossterm

Data Flow

Capture Flow

Hardware     │ Driver Layer │ HAL │ Core │ UI/Analysis
─────────────┼──────────────┼─────┼──────┼─────────────
             │              │     │      │
USB packets  │              │     │      │
    │        │              │     │      │
    v        │              │     │      │
[ CC2531 ]───┼──> read() ───┼──>  │      │
  driver     │   serial     │ Raw │      │
             │   protocol   │Packet     │
             │              │  │  │      │
             │              │  v  │      │
             │              │ traits    │
             │              │  │  │      │
             │              │  v  │      │
             │              │<────┼──────│ capture_packet()
             │              │     │      │
             │              │     v      │
             │              │  parse()  │
             │              │     │      │
             │              │     v      │
             │              │ Parsed    │
             │              │ Packet    │
             │              │     │      │
             │              │     v      │
             │              │<────┼──────│ display/analyze
             │              │     │      │     │
             │              │     │      │     v
             │              │     │      │ [Topology]
             │              │     │      │ [Statistics]
             │              │     │      │ [Display]

Injection Flow (if supported)

UI/Code   │ Core │ HAL │ Driver │ Hardware
──────────┼──────┼─────┼────────┼─────────
          │      │     │        │
create    │      │     │        │
RawPacket │      │     │        │
   │      │      │     │        │
   v      │      │     │        │
inject_packet()─>│     │        │
          │      │     │        │
          │      v     │        │
          │   trait    │        │
          │   method   │        │
          │      │     │        │
          │      v     │        │
          │<───────────┼> write()
          │      │     │  serial
          │      │     │  protocol
          │      │     │    │
          │      │     │    v
          │      │     │ [ CC2531 ]
          │      │     │  transmit
          │      │     │    │
          │      │     │    v
          │      │     │  RF out )))

Error Handling

Comprehensive error types at each layer:

// HAL errors
pub enum HalError {
    DeviceNotFound,
    InitializationFailed,
    CommunicationError(String),
    Timeout,
    InvalidChannel(u8),
    NotSupported,
}

// Parse errors
pub enum ParseError {
    InvalidLength,
    InvalidFrameType,
    ChecksumMismatch,
    MalformedFrame(String),
}

// Crypto errors
pub enum CryptoError {
    InvalidKey,
    DecryptionFailed,
    InvalidNonce,
}

Concurrency Model

  • Async/await: All I/O operations are async
  • Channels: tokio::mpsc for inter-task communication
  • Shared state: Arc<Mutex<>> for thread-safe sharing
  • Lock-free: Packet buffers use crossbeam channels
// Example: Concurrent packet processing
let (tx, mut rx) = mpsc::channel(1000);

// Capture task
tokio::spawn(async move {
    loop {
        let packet = driver.capture_packet().await?;
        tx.send(packet).await?;
    }
});

// Processing task
tokio::spawn(async move {
    while let Some(packet) = rx.recv().await {
        analyze_packet(packet).await;
    }
});

Testing Strategy

Each crate includes:

  1. Unit tests: Test individual functions and types
  2. Integration tests: Test crate boundaries
  3. Mock drivers: Simulate hardware for testing
  4. Fuzzing: Protocol parser fuzzing with cargo-fuzz
# Run all tests
cargo test --all

# Run with coverage
cargo tarpaulin --all

# Fuzz packet parser
cd zigbee-core
cargo fuzz run parse_mac_frame

Performance Considerations

  • Zero-copy parsing: Use nom for zero-copy parsing where possible
  • Buffer pooling: Reuse packet buffers to reduce allocations
  • Batch processing: Process packets in batches for efficiency
  • Lock-free queues: Use crossbeam for high-throughput queues

Benchmarks:

cargo bench --all

Security Considerations

  • Input validation: All packet data is untrusted
  • Safe parsing: Use nom combinators to prevent overflows
  • Careful crypto: Use audited crypto libraries
  • No unsafe: Minimize unsafe code, document when necessary

Future Architecture Plans

  1. Plugin system: Dynamic loading of custom analysis modules
  2. Web UI: Browser-based interface alongside TUI
  3. Distributed capture: Multiple capture nodes coordinated
  4. Cloud storage: Optional cloud backup of captures
  5. Machine learning: Anomaly detection using ML models

See Also:

Clone this wiki locally