1use std::{fmt, io, mem::size_of, num::NonZeroI32};
4
5use crate::{emit_i32, parse_i32, Emitable, Field, Parseable, Rest};
6
7const CODE: Field = 0..4;
8const PAYLOAD: Rest = 4..;
9const ERROR_HEADER_LEN: usize = PAYLOAD.start;
10
11pub trait ErrorContext<T: std::fmt::Display> {
12 fn context(self, msg: T) -> Self;
14
15 fn with_context<F>(self, f: F) -> Self
18 where
19 F: FnOnce() -> T,
20 Self: Sized,
21 {
22 self.context(f())
23 }
24}
25
26#[derive(Debug)]
27pub struct DecodeError {
28 msg: String,
29}
30
31impl<T: std::fmt::Display> ErrorContext<T> for DecodeError {
32 fn context(self, msg: T) -> Self {
33 Self {
34 msg: format!("{} caused by {}", msg, self.msg),
35 }
36 }
37}
38
39impl<T, M> ErrorContext<M> for Result<T, DecodeError>
40where
41 M: std::fmt::Display,
42{
43 fn context(self, msg: M) -> Result<T, DecodeError> {
44 match self {
45 Ok(t) => Ok(t),
46 Err(e) => Err(e.context(msg)),
47 }
48 }
49
50 fn with_context<F>(self, f: F) -> Result<T, DecodeError>
52 where
53 F: FnOnce() -> M,
54 {
55 match self {
56 Ok(t) => Ok(t),
57 Err(e) => Err(e.context(f())),
58 }
59 }
60}
61
62impl From<&str> for DecodeError {
63 fn from(msg: &str) -> Self {
64 Self {
65 msg: msg.to_string(),
66 }
67 }
68}
69
70impl From<String> for DecodeError {
71 fn from(msg: String) -> Self {
72 Self { msg }
73 }
74}
75
76impl From<std::string::FromUtf8Error> for DecodeError {
77 fn from(err: std::string::FromUtf8Error) -> Self {
78 Self {
79 msg: format!("Invalid UTF-8 sequence: {}", err),
80 }
81 }
82}
83
84impl std::fmt::Display for DecodeError {
85 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86 write!(f, "{}", self.msg)
87 }
88}
89
90impl std::error::Error for DecodeError {}
91
92impl DecodeError {
93 pub fn invalid_buffer(
94 name: &str,
95 received: usize,
96 minimum_length: usize,
97 ) -> Self {
98 Self {
99 msg: format!(
100 "Invalid buffer {name}. Expected at least {minimum_length} \
101 bytes, received {received} bytes"
102 ),
103 }
104 }
105 pub fn invalid_mac_address(received: usize) -> Self {
106 Self {
107 msg: format!(
108 "Invalid MAC address. Expected 6 bytes, received {received} \
109 bytes"
110 ),
111 }
112 }
113
114 pub fn invalid_ip_address(received: usize) -> Self {
115 Self {
116 msg: format!(
117 "Invalid IP address. Expected 4 or 16 bytes, received \
118 {received} bytes"
119 ),
120 }
121 }
122
123 pub fn invalid_number(expected: usize, received: usize) -> Self {
124 Self {
125 msg: format!(
126 "Invalid number. Expected {expected} bytes, received \
127 {received} bytes"
128 ),
129 }
130 }
131
132 pub fn nla_buffer_too_small(buffer_len: usize, nla_len: usize) -> Self {
133 Self {
134 msg: format!(
135 "buffer has length {buffer_len}, but an NLA header is \
136 {nla_len} bytes"
137 ),
138 }
139 }
140
141 pub fn nla_length_mismatch(buffer_len: usize, nla_len: usize) -> Self {
142 Self {
143 msg: format!(
144 "buffer has length: {buffer_len}, but the NLA is {nla_len} \
145 bytes"
146 ),
147 }
148 }
149
150 pub fn nla_invalid_length(buffer_len: usize, nla_len: usize) -> Self {
151 Self {
152 msg: format!(
153 "NLA has invalid length: {nla_len} (should be at least \
154 {buffer_len} bytes)"
155 ),
156 }
157 }
158
159 pub fn buffer_too_small(buffer_len: usize, value_len: usize) -> Self {
160 Self {
161 msg: format!(
162 "Buffer too small: {buffer_len} (should be at least \
163 {value_len} bytes"
164 ),
165 }
166 }
167}
168
169#[derive(Debug, PartialEq, Eq, Clone)]
170#[non_exhaustive]
171pub struct ErrorBuffer<T> {
172 buffer: T,
173}
174
175impl<T: AsRef<[u8]>> ErrorBuffer<T> {
176 pub fn new(buffer: T) -> ErrorBuffer<T> {
177 ErrorBuffer { buffer }
178 }
179
180 pub fn into_inner(self) -> T {
182 self.buffer
183 }
184
185 pub fn new_checked(buffer: T) -> Result<Self, DecodeError> {
186 let packet = Self::new(buffer);
187 packet
188 .check_buffer_length()
189 .context("invalid ErrorBuffer length")?;
190 Ok(packet)
191 }
192
193 fn check_buffer_length(&self) -> Result<(), DecodeError> {
194 let len = self.buffer.as_ref().len();
195 if len < ERROR_HEADER_LEN {
196 Err(DecodeError {
197 msg: format!(
198 "invalid ErrorBuffer: length is {len} but ErrorBuffer are \
199 at least {ERROR_HEADER_LEN} bytes"
200 ),
201 })
202 } else {
203 Ok(())
204 }
205 }
206
207 pub fn code(&self) -> Option<NonZeroI32> {
213 let data = self.buffer.as_ref();
214 NonZeroI32::new(parse_i32(&data[CODE]).unwrap())
215 }
216}
217
218impl<'a, T: AsRef<[u8]> + ?Sized> ErrorBuffer<&'a T> {
219 pub fn payload(&self) -> &'a [u8] {
221 let data = self.buffer.as_ref();
222 &data[PAYLOAD]
223 }
224}
225
226impl<T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> ErrorBuffer<&mut T> {
227 pub fn payload_mut(&mut self) -> &mut [u8] {
229 let data = self.buffer.as_mut();
230 &mut data[PAYLOAD]
231 }
232}
233
234impl<T: AsRef<[u8]> + AsMut<[u8]>> ErrorBuffer<T> {
235 pub fn set_code(&mut self, value: i32) {
237 let data = self.buffer.as_mut();
238 emit_i32(&mut data[CODE], value).unwrap();
239 }
240}
241
242#[derive(Debug, Default, Clone, PartialEq, Eq)]
249#[non_exhaustive]
250pub struct ErrorMessage {
251 pub code: Option<NonZeroI32>,
261 pub header: Vec<u8>,
263}
264
265impl Emitable for ErrorMessage {
266 fn buffer_len(&self) -> usize {
267 size_of::<i32>() + self.header.len()
268 }
269 fn emit(&self, buffer: &mut [u8]) {
270 let mut buffer = ErrorBuffer::new(buffer);
271 buffer.set_code(self.raw_code());
272 buffer.payload_mut().copy_from_slice(&self.header)
273 }
274}
275
276impl<T: AsRef<[u8]>> Parseable<ErrorBuffer<&T>> for ErrorMessage {
277 fn parse(buf: &ErrorBuffer<&T>) -> Result<ErrorMessage, DecodeError> {
278 Ok(ErrorMessage {
287 code: buf.code(),
288 header: buf.payload().to_vec(),
289 })
290 }
291}
292
293impl ErrorMessage {
294 pub fn raw_code(&self) -> i32 {
296 self.code.map_or(0, NonZeroI32::get)
297 }
298
299 pub fn to_io(&self) -> io::Error {
305 io::Error::from_raw_os_error(self.raw_code().abs())
306 }
307}
308
309impl fmt::Display for ErrorMessage {
310 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
311 fmt::Display::fmt(&self.to_io(), f)
312 }
313}
314
315impl From<ErrorMessage> for io::Error {
316 fn from(e: ErrorMessage) -> io::Error {
317 e.to_io()
318 }
319}
320
321#[cfg(not(target_endian = "big"))]
323#[cfg(test)]
324mod tests {
325 use super::*;
326
327 #[test]
328 fn into_io_error() {
329 let io_err = io::Error::from_raw_os_error(95);
330 let err_msg = ErrorMessage {
331 code: NonZeroI32::new(-95),
332 header: vec![],
333 };
334
335 let to_io: io::Error = err_msg.to_io();
336
337 assert_eq!(err_msg.to_string(), io_err.to_string());
338 assert_eq!(to_io.raw_os_error(), io_err.raw_os_error());
339 }
340
341 #[test]
342 fn parse_ack() {
343 let bytes = vec![0, 0, 0, 0];
344 let msg = ErrorBuffer::new_checked(&bytes)
345 .and_then(|buf| ErrorMessage::parse(&buf))
346 .expect("failed to parse NLMSG_ERROR");
347 assert_eq!(
348 ErrorMessage {
349 code: None,
350 header: Vec::new()
351 },
352 msg
353 );
354 assert_eq!(msg.raw_code(), 0);
355 }
356
357 #[test]
358 fn parse_nack() {
359 const ERROR_CODE: NonZeroI32 = NonZeroI32::new(-1234).unwrap();
361 let mut bytes = vec![0, 0, 0, 0];
362 emit_i32(&mut bytes, ERROR_CODE.get()).unwrap();
363 let msg = ErrorBuffer::new_checked(&bytes)
364 .and_then(|buf| ErrorMessage::parse(&buf))
365 .expect("failed to parse NLMSG_ERROR");
366 assert_eq!(
367 ErrorMessage {
368 code: Some(ERROR_CODE),
369 header: Vec::new()
370 },
371 msg
372 );
373 assert_eq!(msg.raw_code(), ERROR_CODE.get());
374 }
375}