smb_server_proto_smb1/
rw.rs1use smb_server_proto::types::Status;
22
23pub mod write_offs {
27 pub const ANDX_COMMAND: usize = 0;
29 pub const ANDX_RESERVED: usize = 1;
31 pub const ANDX_OFFSET: usize = 2;
33 pub const FID: usize = 4;
35 pub const OFFSET_LOW: usize = 6;
37 pub const TIMEOUT: usize = 10;
39 pub const WRITE_MODE: usize = 14;
41 pub const REMAINING: usize = 16;
43 pub const DATA_LENGTH_HIGH: usize = 18;
45 pub const DATA_LENGTH: usize = 20;
47 pub const DATA_OFFSET: usize = 22;
49 pub const OFFSET_HIGH: usize = 24;
51
52 pub const MIN_WORDS_BYTES: usize = 24;
54}
55
56pub mod read_offs {
59 pub const FID: usize = 4;
61 pub const OFFSET_LOW: usize = 6;
63 pub const MAX_COUNT: usize = 10;
65 pub const MIN_COUNT: usize = 12;
67 pub const OFFSET_HIGH: usize = 20;
69}
70
71fn g16(b: &[u8], off: usize) -> u16 {
74 b.get(off..off + 2)
75 .map(|s| u16::from_le_bytes([s[0], s[1]]))
76 .unwrap_or(0)
77}
78
79fn g32(b: &[u8], off: usize) -> u32 {
80 b.get(off..off + 4)
81 .map(|s| u32::from_le_bytes(s.try_into().unwrap()))
82 .unwrap_or(0)
83}
84
85#[derive(Debug)]
89pub struct WriteReq {
90 pub fid: u16,
92 pub offset: u64,
94 pub write_through: bool,
96 pub payload: Vec<u8>,
98}
99
100impl WriteReq {
101 pub fn parse(words: &[u8], frame: &[u8]) -> Result<WriteReq, Status> {
107 use write_offs as wo;
108
109 if words.len() < wo::MIN_WORDS_BYTES {
110 return Err(Status::INVALID_PARAMETER);
111 }
112
113 let fid = g16(words, wo::FID);
114 let offset_low = g32(words, wo::OFFSET_LOW);
115 let write_mode = g16(words, wo::WRITE_MODE);
116
117 let len_high = g16(words, wo::DATA_LENGTH_HIGH) as usize;
119 let len_low = g16(words, wo::DATA_LENGTH) as usize;
120 let data_len = (len_high << 16) | len_low;
121
122 let data_off = g16(words, wo::DATA_OFFSET) as usize;
124
125 let mut offset = offset_low as u64;
127 if words.len() >= wo::OFFSET_HIGH + 4 {
128 offset |= (g32(words, wo::OFFSET_HIGH) as u64) << 32;
129 }
130
131 let frame_len = frame.len();
133 if data_off < 32 || data_off + data_len > frame_len || data_len == 0 {
134 return Err(Status::INVALID_PARAMETER);
135 }
136
137 Ok(WriteReq {
138 fid,
139 offset,
140 write_through: write_mode & 0x0001 != 0,
141 payload: frame[data_off..data_off + data_len].to_vec(),
142 })
143 }
144}
145
146pub fn write_response(written: u64) -> Vec<u8> {
150 let mut p = Vec::with_capacity(12);
151 p.push(0xFF); p.push(0);
153 p.extend_from_slice(&0u16.to_le_bytes()); p.extend_from_slice(&(written as u16).to_le_bytes()); p.extend_from_slice(&65535u16.to_le_bytes()); p.extend_from_slice(&((written >> 16) as u16).to_le_bytes()); p.extend_from_slice(&0u16.to_le_bytes()); p
159}
160
161#[derive(Debug)]
165pub struct ReadReq {
166 pub fid: u16,
168 pub offset: u64,
170 pub max_count: usize,
172}
173
174impl ReadReq {
175 pub fn parse(words: &[u8]) -> Result<ReadReq, Status> {
177 use read_offs as ro;
178
179 if words.len() < ro::MIN_COUNT + 2 {
180 return Err(Status::INVALID_PARAMETER);
181 }
182
183 let fid = g16(words, ro::FID);
184 let mut offset = g32(words, ro::OFFSET_LOW) as u64;
185 let max_count = g16(words, ro::MAX_COUNT) as usize;
186
187 if words.len() >= ro::OFFSET_HIGH + 4 {
189 let hi = g32(words, ro::OFFSET_HIGH);
190 offset |= (hi as u64) << 32;
191 }
192
193 Ok(ReadReq { fid, offset, max_count })
194 }
195}
196
197pub fn read_response(data: &[u8]) -> (Vec<u8>, Vec<u8>) {
205 const PARAMS_LEN: usize = 24; const DATA_LEN_OFF: usize = 10;
208 const DATA_OFFS_OFF: usize = 12;
209
210 let bc_end = 32 + 1 + PARAMS_LEN + 2;
212 let doff = (bc_end + 1) & !1usize; let mut params = Vec::with_capacity(PARAMS_LEN);
215 params.push(0xFF); params.push(0);
217 params.extend_from_slice(&0u16.to_le_bytes()); params.extend_from_slice(&0u16.to_le_bytes()); params.extend_from_slice(&0u16.to_le_bytes()); params.extend_from_slice(&0u16.to_le_bytes()); params.extend_from_slice(&(data.len() as u16).to_le_bytes()); params.extend_from_slice(&(doff as u16).to_le_bytes()); params.extend_from_slice(&0u32.to_le_bytes()); params.extend_from_slice(&[0u8; 6]); debug_assert_eq!(params.len(), PARAMS_LEN);
227 debug_assert_eq!(
228 u16::from_le_bytes(params[DATA_LEN_OFF..DATA_LEN_OFF + 2].try_into().unwrap()),
229 data.len() as u16
230 );
231 debug_assert_eq!(
232 u16::from_le_bytes(params[DATA_OFFS_OFF..DATA_OFFS_OFF + 2].try_into().unwrap()),
233 doff as u16
234 );
235
236 let pad = doff - bc_end;
237 let mut bytes = vec![0u8; pad];
238 bytes.extend_from_slice(data);
239 (params, bytes)
240}