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}