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