1use binrw::prelude::*;
4
5use smb_dtyp::binrw_util::prelude::*;
6
7#[binrw::binrw]
8#[derive(Debug, PartialEq, Eq)]
9pub struct ErrorResponse {
10 #[bw(calc = 9)]
11 #[br(assert(_structure_size == 9))]
12 _structure_size: u16,
13
14 #[bw(try_calc = error_data.len().try_into())]
15 _error_context_count: u8,
16
17 #[br(assert(_reserved == 0))]
18 #[bw(calc = 0)]
19 _reserved: u8,
20
21 #[bw(calc = PosMarker::default())]
22 _byte_count: PosMarker<u32>,
23
24 #[br(count = _error_context_count)]
25 pub error_data: Vec<ErrorResponseContext>,
26}
27
28#[binrw::binrw]
29#[derive(Debug, PartialEq, Eq)]
30pub struct ErrorResponseContext {
31 #[brw(align_before = 8)]
35 #[bw(try_calc = error_data.len().try_into())]
36 _error_data_length: u32,
37 pub error_id: ErrorId,
38 #[br(count = _error_data_length)]
39 pub error_data: Vec<u8>,
40}
41
42impl ErrorResponse {
43 pub fn find_context(&self, id: ErrorId) -> Option<&ErrorResponseContext> {
46 self.error_data.iter().find(|c| c.error_id == id)
47 }
48}
49
50impl ErrorResponseContext {
51 pub fn as_u32(&self) -> crate::Result<u32> {
54 if self.error_data.len() == std::mem::size_of::<u32>() {
55 Ok(u32::from_le_bytes(
56 self.error_data.as_slice().try_into().unwrap(),
57 ))
58 } else {
59 Err(crate::SmbMsgError::InvalidData(
60 "Invalid error data length for u32".into(),
61 ))
62 }
63 }
64
65 pub fn as_u64(&self) -> crate::Result<u64> {
68 if self.error_data.len() == std::mem::size_of::<u64>() {
69 Ok(u64::from_le_bytes(
70 self.error_data.as_slice().try_into().unwrap(),
71 ))
72 } else {
73 Err(crate::SmbMsgError::InvalidData(
74 "Invalid error data length for u64".into(),
75 ))
76 }
77 }
78}
79
80#[binrw::binrw]
81#[derive(Debug, PartialEq, Eq)]
82#[brw(repr(u32))]
83pub enum ErrorId {
84 Default = 0,
85 ShareRedirect = 0x72645253,
86}
87
88#[cfg(test)]
89mod tests {
90 use crate::*;
91
92 use super::*;
93
94 #[test]
95 pub fn test_simple_error_pasrsed() {
96 let msg = decode_content(&[
97 0xfe, 0x53, 0x4d, 0x42, 0x40, 0x0, 0x1, 0x0, 0x34, 0x0, 0x0, 0xc0, 0x5, 0x0, 0x1, 0x0,
98 0x19, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
99 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x71, 0x0, 0x0, 0x28, 0x0, 0x30, 0x0, 0x0, 0xf7,
100 0xd, 0xa6, 0x1d, 0x9b, 0x2c, 0x43, 0xd3, 0x26, 0x88, 0x74, 0xf, 0xdf, 0x47, 0x59, 0x24,
101 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
102 ]);
103 assert_eq!(msg.header.status, Status::ObjectNameNotFound as u32);
104 let msg = match msg.content {
105 ResponseContent::Error(msg) => msg,
106 _ => panic!("Unexpected response"),
107 };
108 assert_eq!(msg, ErrorResponse { error_data: vec![] })
109 }
110}