Skip to content

Commit f55d7b7

Browse files
qinqoncathay4t
authored andcommitted
errors: Copy DecodeError from netlink-core-utils
Signed-off-by: Enrique Llorente <ellorent@redhat.com>
1 parent 01e8dd1 commit f55d7b7

File tree

5 files changed

+117
-35
lines changed

5 files changed

+117
-35
lines changed

src/buffer.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
// SPDX-License-Identifier: MIT
22

33
use byteorder::{ByteOrder, NativeEndian};
4-
use netlink_packet_utils::DecodeError;
54

6-
use crate::{Field, Rest};
5+
use crate::{DecodeError, ErrorContext, Field, Rest};
76

87
const LENGTH: Field = 0..4;
98
const MESSAGE_TYPE: Field = 4..6;
@@ -158,7 +157,7 @@ impl<T: AsRef<[u8]>> NetlinkBuffer<T> {
158157
/// ```
159158
pub fn new_checked(buffer: T) -> Result<NetlinkBuffer<T>, DecodeError> {
160159
let packet = Self::new(buffer);
161-
packet.check_buffer_length()?;
160+
packet.check_buffer_length().context("invalid netlink buffer length")?;
162161
Ok(packet)
163162
}
164163

@@ -331,7 +330,7 @@ impl<'a, T: AsRef<[u8]> + ?Sized> NetlinkBuffer<&'a T> {
331330
}
332331
}
333332

334-
impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> NetlinkBuffer<&'a mut T> {
333+
impl<T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> NetlinkBuffer<&mut T> {
335334
/// Return a mutable pointer to the payload.
336335
///
337336
/// # Panic

src/done.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
use std::mem::size_of;
44

55
use byteorder::{ByteOrder, NativeEndian};
6-
use netlink_packet_utils::DecodeError;
76

8-
use crate::{Emitable, Field, Parseable, Rest};
7+
use crate::{DecodeError, Emitable, ErrorContext, Field, Parseable, Rest};
98

109
const CODE: Field = 0..4;
1110
const EXTENDED_ACK: Rest = 4..;
@@ -29,7 +28,9 @@ impl<T: AsRef<[u8]>> DoneBuffer<T> {
2928

3029
pub fn new_checked(buffer: T) -> Result<Self, DecodeError> {
3130
let packet = Self::new(buffer);
32-
packet.check_buffer_length()?;
31+
packet
32+
.check_buffer_length()
33+
.context("invalid DoneBuffer length")?;
3334
Ok(packet)
3435
}
3536

@@ -61,7 +62,7 @@ impl<'a, T: AsRef<[u8]> + ?Sized> DoneBuffer<&'a T> {
6162
}
6263
}
6364

64-
impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> DoneBuffer<&'a mut T> {
65+
impl<T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> DoneBuffer<&mut T> {
6566
/// Return a mutable pointer to the extended ack attributes.
6667
pub fn extended_ack_mut(&mut self) -> &mut [u8] {
6768
let data = self.buffer.as_mut();

src/error.rs

Lines changed: 89 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,92 @@
33
use std::{fmt, io, mem::size_of, num::NonZeroI32};
44

55
use byteorder::{ByteOrder, NativeEndian};
6-
use netlink_packet_utils::DecodeError;
76

87
use crate::{Emitable, Field, Parseable, Rest};
98

109
const CODE: Field = 0..4;
1110
const PAYLOAD: Rest = 4..;
1211
const ERROR_HEADER_LEN: usize = PAYLOAD.start;
1312

13+
pub trait ErrorContext {
14+
fn context(self, msg: &str) -> Self;
15+
}
16+
17+
#[derive(Debug)]
18+
pub struct DecodeError {
19+
msg: String,
20+
}
21+
22+
impl ErrorContext for DecodeError {
23+
fn context(self, msg: &str) -> Self {
24+
Self {
25+
msg: format!("{} caused by {}", msg, self.msg),
26+
}
27+
}
28+
}
29+
30+
impl<T> ErrorContext for Result<T, DecodeError>
31+
where
32+
T: Clone,
33+
{
34+
fn context(self, msg: &str) -> Result<T, DecodeError> {
35+
match self {
36+
Ok(t) => Ok(t),
37+
Err(e) => Err(e.context(msg)),
38+
}
39+
}
40+
}
41+
42+
impl From<&str> for DecodeError {
43+
fn from(msg: &str) -> Self {
44+
Self {
45+
msg: msg.to_string(),
46+
}
47+
}
48+
}
49+
50+
impl From<String> for DecodeError {
51+
fn from(msg: String) -> Self {
52+
Self { msg }
53+
}
54+
}
55+
56+
impl From<std::string::FromUtf8Error> for DecodeError {
57+
fn from(err: std::string::FromUtf8Error) -> Self {
58+
Self {
59+
msg: format!("Invalid UTF-8 sequence: {}", err),
60+
}
61+
}
62+
}
63+
64+
impl std::fmt::Display for DecodeError {
65+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66+
write!(f, "{}", self.msg)
67+
}
68+
}
69+
70+
impl std::error::Error for DecodeError {}
71+
72+
impl DecodeError {
73+
pub fn invalid_mac_address(received: usize) -> Self {
74+
Self{
75+
msg: format!("Invalid MAC address. Expected 6 bytes, received {received} bytes"),
76+
}
77+
}
78+
79+
pub fn invalid_ip_address(received: usize) -> Self {
80+
Self{
81+
msg: format!("Invalid IP address. Expected 4 or 16 bytes, received {received} bytes"),
82+
}
83+
}
84+
85+
pub fn invalid_number(expected: usize, received: usize) -> Self {
86+
Self{
87+
msg: format!("Invalid number. Expected {expected} bytes, received {received} bytes"),
88+
}
89+
}
90+
}
91+
1492
#[derive(Debug, PartialEq, Eq, Clone)]
1593
#[non_exhaustive]
1694
pub struct ErrorBuffer<T> {
@@ -29,18 +107,21 @@ impl<T: AsRef<[u8]>> ErrorBuffer<T> {
29107

30108
pub fn new_checked(buffer: T) -> Result<Self, DecodeError> {
31109
let packet = Self::new(buffer);
32-
packet.check_buffer_length()?;
110+
packet
111+
.check_buffer_length()
112+
.context("invalid ErrorBuffer length")?;
33113
Ok(packet)
34114
}
35115

36116
fn check_buffer_length(&self) -> Result<(), DecodeError> {
37117
let len = self.buffer.as_ref().len();
38118
if len < ERROR_HEADER_LEN {
39-
Err(format!(
40-
"invalid ErrorBuffer: length is {len} but ErrorBuffer are \
119+
Err(DecodeError {
120+
msg: format!(
121+
"invalid ErrorBuffer: length is {len} but ErrorBuffer are \
41122
at least {ERROR_HEADER_LEN} bytes"
42-
)
43-
.into())
123+
),
124+
})
44125
} else {
45126
Ok(())
46127
}
@@ -65,7 +146,7 @@ impl<'a, T: AsRef<[u8]> + ?Sized> ErrorBuffer<&'a T> {
65146
}
66147
}
67148

68-
impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> ErrorBuffer<&'a mut T> {
149+
impl<T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> ErrorBuffer<&mut T> {
69150
/// Return a mutable pointer to the payload.
70151
pub fn payload_mut(&mut self) -> &mut [u8] {
71152
let data = self.buffer.as_mut();
@@ -199,8 +280,7 @@ mod tests {
199280
#[test]
200281
fn parse_nack() {
201282
// SAFETY: value is non-zero.
202-
const ERROR_CODE: NonZeroI32 =
203-
unsafe { NonZeroI32::new_unchecked(-1234) };
283+
const ERROR_CODE: NonZeroI32 = NonZeroI32::new(-1234).unwrap();
204284
let mut bytes = vec![0, 0, 0, 0];
205285
NativeEndian::write_i32(&mut bytes, ERROR_CODE.get());
206286
let msg = ErrorBuffer::new_checked(&bytes)

src/header.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// SPDX-License-Identifier: MIT
22

3-
use netlink_packet_utils::DecodeError;
4-
5-
use crate::{buffer::NETLINK_HEADER_LEN, Emitable, NetlinkBuffer, Parseable};
3+
use crate::{
4+
buffer::NETLINK_HEADER_LEN, DecodeError, Emitable, NetlinkBuffer, Parseable,
5+
};
66

77
/// A Netlink header representation. A netlink header has the following
88
/// structure:
@@ -111,7 +111,7 @@ mod tests {
111111
port_number: 0,
112112
};
113113
assert_eq!(repr.buffer_len(), 16);
114-
let mut buf = vec![0; 16];
114+
let mut buf = [0; 16];
115115
repr.emit(&mut buf[..]);
116116
assert_eq!(&buf[..], &IP_LINK_SHOW_PKT[..16]);
117117
}

src/message.rs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@
22

33
use std::fmt::Debug;
44

5-
use netlink_packet_utils::DecodeError;
6-
75
use crate::{
86
payload::{NLMSG_DONE, NLMSG_ERROR, NLMSG_NOOP, NLMSG_OVERRUN},
9-
DoneBuffer, DoneMessage, Emitable, ErrorBuffer, ErrorMessage,
10-
NetlinkBuffer, NetlinkDeserializable, NetlinkHeader, NetlinkPayload,
11-
NetlinkSerializable, Parseable,
7+
DecodeError, DoneBuffer, DoneMessage, Emitable, ErrorBuffer, ErrorContext,
8+
ErrorMessage, NetlinkBuffer, NetlinkDeserializable, NetlinkHeader,
9+
NetlinkPayload, NetlinkSerializable, Parseable,
1210
};
1311

1412
/// Represent a netlink message.
@@ -39,7 +37,8 @@ where
3937
{
4038
/// Parse the given buffer as a netlink message
4139
pub fn deserialize(buffer: &[u8]) -> Result<Self, DecodeError> {
42-
let netlink_buffer = NetlinkBuffer::new_checked(&buffer)?;
40+
let netlink_buffer = NetlinkBuffer::new_checked(&buffer)
41+
.context("failed deserializing NetlinkMessage")?;
4342
<Self as Parseable<NetlinkBuffer<&&[u8]>>>::parse(&netlink_buffer)
4443
}
4544
}
@@ -93,27 +92,31 @@ where
9392
use self::NetlinkPayload::*;
9493

9594
let header =
96-
<NetlinkHeader as Parseable<NetlinkBuffer<&B>>>::parse(buf)?;
95+
<NetlinkHeader as Parseable<NetlinkBuffer<&B>>>::parse(buf)
96+
.context("failed parsing NetlinkHeader")?;
9797

9898
let bytes = buf.payload();
9999
let payload = match header.message_type {
100100
NLMSG_ERROR => {
101101
let msg = ErrorBuffer::new_checked(&bytes)
102-
.and_then(|buf| ErrorMessage::parse(&buf))?;
102+
.and_then(|buf| ErrorMessage::parse(&buf))
103+
.context("failed parsing NLMSG_ERROR")?;
103104
Error(msg)
104105
}
105106
NLMSG_NOOP => Noop,
106107
NLMSG_DONE => {
107108
let msg = DoneBuffer::new_checked(&bytes)
108-
.and_then(|buf| DoneMessage::parse(&buf))?;
109+
.and_then(|buf| DoneMessage::parse(&buf))
110+
.context("failed parsing NLMSG_DONE")?;
109111
Done(msg)
110112
}
111113
NLMSG_OVERRUN => Overrun(bytes.to_vec()),
112114
message_type => match I::deserialize(&header, bytes) {
113115
Err(e) => {
114-
return Err(DecodeError::Other(
115-
format!("Failed to parse message with type {message_type}: {e}").into()),
116-
);
116+
return Err(format!(
117+
"Failed to parse message with type {message_type}: {e}"
118+
)
119+
.into())
117120
}
118121
Ok(inner_msg) => InnerMessage(inner_msg),
119122
},
@@ -238,8 +241,7 @@ mod tests {
238241
#[test]
239242
fn test_error() {
240243
// SAFETY: value is non-zero.
241-
const ERROR_CODE: NonZeroI32 =
242-
unsafe { NonZeroI32::new_unchecked(-8765) };
244+
const ERROR_CODE: NonZeroI32 = NonZeroI32::new(-8765).unwrap();
243245

244246
let header = NetlinkHeader::default();
245247
let error_msg = ErrorMessage {

0 commit comments

Comments
 (0)