11// SPDX-License-Identifier: MIT
22
3- use std:: { fmt, io, mem:: size_of, num :: NonZeroI32 } ;
3+ use std:: { fmt, io, mem:: size_of} ;
44
55use byteorder:: { ByteOrder , NativeEndian } ;
66use netlink_packet_utils:: DecodeError ;
@@ -46,14 +46,10 @@ impl<T: AsRef<[u8]>> ErrorBuffer<T> {
4646 }
4747 }
4848
49- /// Return the error code.
50- ///
51- /// Returns `None` when there is no error to report (the message is an ACK),
52- /// or a `Some(e)` if there is a non-zero error code `e` to report (the
53- /// message is a NACK).
54- pub fn code ( & self ) -> Option < NonZeroI32 > {
49+ /// Return the error code
50+ pub fn code ( & self ) -> i32 {
5551 let data = self . buffer . as_ref ( ) ;
56- NonZeroI32 :: new ( NativeEndian :: read_i32 ( & data[ CODE ] ) )
52+ NativeEndian :: read_i32 ( & data[ CODE ] )
5753 }
5854}
5955
@@ -81,36 +77,22 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> ErrorBuffer<T> {
8177 }
8278}
8379
84- /// An `NLMSG_ERROR` message.
85- ///
86- /// Per [RFC 3549 section 2.3.2.2], this message carries the return code for a
87- /// request which will indicate either success (an ACK) or failure (a NACK).
88- ///
89- /// [RFC 3549 section 2.3.2.2]: https://datatracker.ietf.org/doc/html/rfc3549#section-2.3.2.2
9080#[ derive( Debug , Default , Clone , PartialEq , Eq ) ]
9181#[ non_exhaustive]
9282pub struct ErrorMessage {
93- /// The error code.
94- ///
95- /// Holds `None` when there is no error to report (the message is an ACK),
96- /// or a `Some(e)` if there is a non-zero error code `e` to report (the
97- /// message is a NACK).
98- ///
99- /// See [Netlink message types] for details.
100- ///
101- /// [Netlink message types]: https://kernel.org/doc/html/next/userspace-api/netlink/intro.html#netlink-message-types
102- pub code : Option < NonZeroI32 > ,
103- /// The original request's header.
83+ pub code : i32 ,
10484 pub header : Vec < u8 > ,
10585}
10686
87+ pub type AckMessage = ErrorMessage ;
88+
10789impl Emitable for ErrorMessage {
10890 fn buffer_len ( & self ) -> usize {
10991 size_of :: < i32 > ( ) + self . header . len ( )
11092 }
11193 fn emit ( & self , buffer : & mut [ u8 ] ) {
11294 let mut buffer = ErrorBuffer :: new ( buffer) ;
113- buffer. set_code ( self . raw_code ( ) ) ;
95+ buffer. set_code ( self . code ) ;
11496 buffer. payload_mut ( ) . copy_from_slice ( & self . header )
11597 }
11698}
@@ -137,18 +119,13 @@ impl<'buffer, T: AsRef<[u8]> + 'buffer> Parseable<ErrorBuffer<&'buffer T>>
137119}
138120
139121impl ErrorMessage {
140- /// Returns the raw error code.
141- pub fn raw_code ( & self ) -> i32 {
142- self . code . map_or ( 0 , NonZeroI32 :: get)
143- }
144-
145122 /// According to [`netlink(7)`](https://linux.die.net/man/7/netlink)
146123 /// the `NLMSG_ERROR` return Negative errno or 0 for acknowledgements.
147124 ///
148125 /// convert into [`std::io::Error`](https://doc.rust-lang.org/std/io/struct.Error.html)
149126 /// using the absolute value from errno code
150127 pub fn to_io ( & self ) -> io:: Error {
151- io:: Error :: from_raw_os_error ( self . raw_code ( ) . abs ( ) )
128+ io:: Error :: from_raw_os_error ( self . code . abs ( ) )
152129 }
153130}
154131
@@ -172,7 +149,7 @@ mod tests {
172149 fn into_io_error ( ) {
173150 let io_err = io:: Error :: from_raw_os_error ( 95 ) ;
174151 let err_msg = ErrorMessage {
175- code : NonZeroI32 :: new ( -95 ) ,
152+ code : -95 ,
176153 header : vec ! [ ] ,
177154 } ;
178155
@@ -181,40 +158,4 @@ mod tests {
181158 assert_eq ! ( err_msg. to_string( ) , io_err. to_string( ) ) ;
182159 assert_eq ! ( to_io. raw_os_error( ) , io_err. raw_os_error( ) ) ;
183160 }
184-
185- #[ test]
186- fn parse_ack ( ) {
187- let bytes = vec ! [ 0 , 0 , 0 , 0 ] ;
188- let msg = ErrorBuffer :: new_checked ( & bytes)
189- . and_then ( |buf| ErrorMessage :: parse ( & buf) )
190- . expect ( "failed to parse NLMSG_ERROR" ) ;
191- assert_eq ! (
192- ErrorMessage {
193- code: None ,
194- header: Vec :: new( )
195- } ,
196- msg
197- ) ;
198- assert_eq ! ( msg. raw_code( ) , 0 ) ;
199- }
200-
201- #[ test]
202- fn parse_nack ( ) {
203- // SAFETY: value is non-zero.
204- const ERROR_CODE : NonZeroI32 =
205- unsafe { NonZeroI32 :: new_unchecked ( -1234 ) } ;
206- let mut bytes = vec ! [ 0 , 0 , 0 , 0 ] ;
207- NativeEndian :: write_i32 ( & mut bytes, ERROR_CODE . get ( ) ) ;
208- let msg = ErrorBuffer :: new_checked ( & bytes)
209- . and_then ( |buf| ErrorMessage :: parse ( & buf) )
210- . expect ( "failed to parse NLMSG_ERROR" ) ;
211- assert_eq ! (
212- ErrorMessage {
213- code: Some ( ERROR_CODE ) ,
214- header: Vec :: new( )
215- } ,
216- msg
217- ) ;
218- assert_eq ! ( msg. raw_code( ) , ERROR_CODE . get( ) ) ;
219- }
220161}
0 commit comments