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}