Skip to main content

r_lanlib/
error.rs

1//! Custom Error and Result types for this library
2
3use std::{
4    any::Any,
5    num::ParseIntError,
6    sync::{
7        MutexGuard, PoisonError,
8        mpsc::{RecvError, SendError},
9    },
10};
11use thiserror::Error;
12
13use crate::{
14    packet::{
15        arp_packet::ArpPacketBuilderError,
16        heartbeat_packet::HeartbeatPacketBuilderError,
17        rst_packet::RstPacketBuilderError, syn_packet::SynPacketBuilderError,
18    },
19    scanners::{
20        ScanMessage, arp_scanner::ARPScannerBuilderError,
21        heartbeat::HeartBeatBuilderError, syn_scanner::SYNScannerBuilderError,
22    },
23    wire::{Reader, Sender},
24};
25
26/// Custom Error type for this library
27#[derive(Error, Debug)]
28pub enum RLanLibError {
29    /// Error resulting from failures in OuiDb
30    #[error("oui: {_0}")]
31    Oui(String),
32
33    /// Error coming directly off the wire
34    #[error("wire error: {_0}")]
35    Wire(String),
36
37    /// Errors resulting from events channel
38    #[error("failed to send notification message: {:#?}", _0)]
39    NotifierSendError(#[from] SendError<Box<ScanMessage>>),
40
41    /// Error obtaining lock on packet reader
42    #[error("failed to get lock on packet reader: {_0}")]
43    PacketReaderLock(String),
44
45    /// Error obtaining lock on packet sender
46    #[error("failed to get lock on packet sender: {_0}")]
47    PacketSenderLock(String),
48
49    /// Generic thread error
50    #[error("thread error: {_0}")]
51    ThreadError(String),
52
53    /// Errors when consuming messages from channels
54    #[error("failed to receive message from channel: {:#?}", _0)]
55    ChannelReceive(#[from] RecvError),
56
57    /// Error generated during ARP packet construction
58    #[error("failed to build ARP packet: {_0}")]
59    ArpPacketBuild(#[from] ArpPacketBuilderError),
60
61    /// Error resulting from failure to build ARP scanner
62    #[error("failed to build arp scanner: {_0}")]
63    ArpScannerBuild(#[from] ARPScannerBuilderError),
64
65    /// Error resulting from failure to build SYN scanner
66    #[error("failed to build syn scanner: {_0}")]
67    SynScannerBuild(#[from] SYNScannerBuilderError),
68
69    /// Error resulting from failure to build Heartbeat
70    #[error("failed to build heartbeat: {_0}")]
71    HeartBeatBuild(#[from] HeartBeatBuilderError),
72
73    /// Error generated during RST packet construction
74    #[error("failed to build RST packet: {_0}")]
75    RstPacketBuild(#[from] RstPacketBuilderError),
76
77    /// Error generated during SYN packet construction
78    #[error("failed to build SYN packet: {_0}")]
79    SynPacketBuild(#[from] SynPacketBuilderError),
80
81    /// Error generated during heartbeat packet construction
82    #[error("failed to build heartbeat packet: {_0}")]
83    HeartbeatPacketBuild(#[from] HeartbeatPacketBuilderError),
84
85    /// Errors generated accessing device interfaces
86    #[error("network interface error: {_0}")]
87    NetworkInterface(String),
88
89    /// Wrapping errors related to scanning
90    #[error("scanning error: {error} - ip: {:#?}, port: {:#?}", ip, port)]
91    Scan {
92        /// The error message encountered
93        error: String,
94        /// The associated IP address being scanned
95        ip: Option<String>,
96        /// The associated port being scanned
97        port: Option<String>,
98    },
99}
100
101impl From<Box<dyn Any + Send>> for RLanLibError {
102    fn from(value: Box<dyn Any + Send>) -> Self {
103        if let Some(s) = value.downcast_ref::<&'static str>() {
104            Self::ThreadError(format!("Thread panicked with: {}", s))
105        } else if let Some(s) = value.downcast_ref::<String>() {
106            Self::ThreadError(format!("Thread panicked with: {}", s))
107        } else {
108            Self::ThreadError("Thread panicked with an unknown type".into())
109        }
110    }
111}
112
113impl<'a> From<PoisonError<MutexGuard<'a, dyn Reader + 'static>>>
114    for RLanLibError
115{
116    fn from(value: PoisonError<MutexGuard<'a, dyn Reader + 'static>>) -> Self {
117        Self::PacketReaderLock(value.to_string())
118    }
119}
120
121impl<'a> From<PoisonError<MutexGuard<'a, dyn Sender + 'static>>>
122    for RLanLibError
123{
124    fn from(value: PoisonError<MutexGuard<'a, dyn Sender + 'static>>) -> Self {
125        Self::PacketSenderLock(value.to_string())
126    }
127}
128
129impl RLanLibError {
130    /// Converter for std::net::AddrParseError
131    pub fn from_net_addr_parse_error(
132        ip: &str,
133        error: std::net::AddrParseError,
134    ) -> Self {
135        Self::Scan {
136            error: error.to_string(),
137            ip: Some(ip.to_string()),
138            port: None,
139        }
140    }
141
142    /// Converter for ipnet::AddrParseError
143    pub fn from_ipnet_addr_parse_error(
144        ip: &str,
145        error: ipnet::AddrParseError,
146    ) -> Self {
147        Self::Scan {
148            error: error.to_string(),
149            ip: Some(ip.to_string()),
150            port: None,
151        }
152    }
153
154    /// Converter for ParseIntError
155    pub fn from_port_parse_int_err(port: &str, error: ParseIntError) -> Self {
156        Self::Scan {
157            error: error.to_string(),
158            ip: None,
159            port: Some(port.to_string()),
160        }
161    }
162
163    /// Converter for channel send errors
164    pub fn from_channel_send_error(e: SendError<ScanMessage>) -> Self {
165        RLanLibError::NotifierSendError(SendError(Box::from(e.0)))
166    }
167}
168
169unsafe impl Send for RLanLibError {}
170unsafe impl Sync for RLanLibError {}
171
172/// Custom Result type for this library. All Errors exposed by this library
173/// will be returned as [`RLanLibError`]
174pub type Result<T> = std::result::Result<T, RLanLibError>;