netlink_proto/
codecs.rs

1// SPDX-License-Identifier: MIT
2
3use std::{fmt::Debug, io};
4
5use bytes::{BufMut, BytesMut};
6use netlink_packet_core::{
7    NetlinkBuffer,
8    NetlinkDeserializable,
9    NetlinkMessage,
10    NetlinkSerializable,
11};
12
13/// Protocol to serialize and deserialize messages to and from datagrams
14///
15/// This is separate from `tokio_util::codec::{Decoder, Encoder}` as the implementations
16/// rely on the buffer containing full datagrams; they won't work well with simple
17/// bytestreams.
18///
19/// Officially there should be exactly one implementation of this, but the audit
20/// subsystem ignores way too many rules of the protocol, so they need a separate
21/// implementation.
22///
23/// Although one could make a tighter binding between `NetlinkMessageCodec` and
24/// the message types (NetlinkDeserializable+NetlinkSerializable) it can handle,
25/// this would put quite some overhead on subsystems that followed the spec - so
26/// we simply default to the proper implementation (in `Connection`) and the
27/// `audit` code needs to overwrite it.
28pub trait NetlinkMessageCodec {
29    /// Decode message of given type from datagram payload
30    ///
31    /// There might be more than one message; this needs to be called until it
32    /// either returns `Ok(None)` or an error.
33    fn decode<T>(src: &mut BytesMut) -> io::Result<Option<NetlinkMessage<T>>>
34    where
35        T: NetlinkDeserializable + Debug;
36
37    /// Encode message to (datagram) buffer
38    fn encode<T>(msg: NetlinkMessage<T>, buf: &mut BytesMut) -> io::Result<()>
39    where
40        T: NetlinkSerializable + Debug;
41}
42
43/// Standard implementation of `NetlinkMessageCodec`
44pub struct NetlinkCodec {
45    // we don't need an instance of this, just the type
46    _private: (),
47}
48
49impl NetlinkMessageCodec for NetlinkCodec {
50    fn decode<T>(src: &mut BytesMut) -> io::Result<Option<NetlinkMessage<T>>>
51    where
52        T: NetlinkDeserializable + Debug,
53    {
54        debug!("NetlinkCodec: decoding next message");
55
56        loop {
57            // If there's nothing to read, return Ok(None)
58            if src.is_empty() {
59                trace!("buffer is empty");
60                return Ok(None);
61            }
62
63            // This is a bit hacky because we don't want to keep `src`
64            // borrowed, since we need to mutate it later.
65            let len = match NetlinkBuffer::new_checked(src.as_ref()) {
66                Ok(buf) => buf.length() as usize,
67                Err(e) => {
68                    // We either received a truncated packet, or the
69                    // packet if malformed (invalid length field). In
70                    // both case, we can't decode the datagram, and we
71                    // cannot find the start of the next one (if
72                    // any). The only solution is to clear the buffer
73                    // and potentially lose some datagrams.
74                    error!(
75                        "failed to decode datagram, clearing buffer: {:?}: {:#x?}.",
76                        e,
77                        src.as_ref()
78                    );
79                    src.clear();
80                    return Ok(None);
81                }
82            };
83
84            let bytes = src.split_to(len);
85
86            let parsed = NetlinkMessage::<T>::deserialize(&bytes);
87            match parsed {
88                Ok(packet) => {
89                    trace!("<<< {:?}", packet);
90                    return Ok(Some(packet));
91                }
92                Err(e) => {
93                    error!("failed to decode packet {:#x?}: {}", &bytes, e);
94                    // continue looping, there may be more datagrams in the buffer
95                }
96            }
97        }
98    }
99
100    fn encode<T>(msg: NetlinkMessage<T>, buf: &mut BytesMut) -> io::Result<()>
101    where
102        T: Debug + NetlinkSerializable,
103    {
104        let msg_len = msg.buffer_len();
105        if buf.remaining_mut() < msg_len {
106            // BytesMut can expand till usize::MAX... unlikely to hit this one.
107            return Err(io::Error::new(
108                io::ErrorKind::Other,
109                format!(
110                    "message is {} bytes, but only {} bytes left in the buffer",
111                    msg_len,
112                    buf.remaining_mut()
113                ),
114            ));
115        }
116
117        // As NetlinkMessage::serialize needs an initialized buffer anyway
118        // no need for any `unsafe` magic.
119        let old_len = buf.len();
120        let new_len = old_len + msg_len;
121        buf.resize(new_len, 0);
122        msg.serialize(&mut buf[old_len..][..msg_len]);
123        trace!(">>> {:?}", msg);
124        Ok(())
125    }
126}