netlink_packet_generic/
message.rs

1// SPDX-License-Identifier: MIT
2
3//! Message definition and method implementations
4
5use crate::{buffer::GenlBuffer, header::GenlHeader, traits::*};
6use netlink_packet_core::{
7    DecodeError, Emitable, NetlinkDeserializable, NetlinkHeader,
8    NetlinkPayload, NetlinkSerializable, ParseableParametrized,
9};
10use std::fmt::Debug;
11
12#[cfg(doc)]
13use netlink_packet_core::NetlinkMessage;
14
15/// Represent the generic netlink messages
16///
17/// This type can wrap data types `F` which represents a generic family payload.
18/// The message can be serialize/deserialize if the type `F` implements
19/// [`GenlFamily`], [`Emitable`], and [`ParseableParametrized<[u8],
20/// GenlHeader>`](ParseableParametrized).
21#[derive(Clone, Debug, PartialEq, Eq)]
22pub struct GenlMessage<F> {
23    pub header: GenlHeader,
24    pub payload: F,
25    resolved_family_id: u16,
26}
27
28impl<F> GenlMessage<F>
29where
30    F: Debug,
31{
32    /// Construct the message
33    pub fn new(header: GenlHeader, payload: F, family_id: u16) -> Self {
34        Self {
35            header,
36            payload,
37            resolved_family_id: family_id,
38        }
39    }
40
41    /// Construct the message by the given header and payload
42    pub fn from_parts(header: GenlHeader, payload: F) -> Self {
43        Self {
44            header,
45            payload,
46            resolved_family_id: 0,
47        }
48    }
49
50    /// Consume this message and return its header and payload
51    pub fn into_parts(self) -> (GenlHeader, F) {
52        (self.header, self.payload)
53    }
54
55    /// Return the previously set resolved family ID in this message.
56    ///
57    /// This value would be used to serialize the message only if
58    /// the ([`GenlFamily::family_id()`]) return 0 in the underlying type.
59    pub fn resolved_family_id(&self) -> u16 {
60        self.resolved_family_id
61    }
62
63    /// Set the resolved dynamic family ID of the message, if the generic family
64    /// uses dynamic generated ID by kernel.
65    ///
66    /// This method is a interface to provide other high level library to
67    /// set the resolved family ID before the message is serialized.
68    ///
69    /// # Usage
70    /// Normally, you don't have to call this function directly if you are
71    /// using library which helps you handle the dynamic family id.
72    ///
73    /// If you are the developer of some high level generic netlink library,
74    /// you can call this method to set the family id resolved by your resolver.
75    /// Without having to modify the `message_type` field of the serialized
76    /// netlink packet header before sending it.
77    pub fn set_resolved_family_id(&mut self, family_id: u16) {
78        self.resolved_family_id = family_id;
79    }
80}
81
82impl<F> GenlMessage<F>
83where
84    F: GenlFamily + Debug,
85{
86    /// Build the message from the payload
87    ///
88    /// This function would automatically fill the header for you. You can
89    /// directly emit the message without having to call
90    /// [`finalize()`](Self::finalize).
91    pub fn from_payload(payload: F) -> Self {
92        Self {
93            header: GenlHeader {
94                cmd: payload.command(),
95                version: payload.version(),
96            },
97            payload,
98            resolved_family_id: 0,
99        }
100    }
101
102    /// Ensure the header ([`GenlHeader`]) is consistent with the payload (`F:
103    /// GenlFamily`):
104    ///
105    /// - Fill the command and version number into the header
106    ///
107    /// If you are not 100% sure the header is correct, this method should be
108    /// called before calling [`Emitable::emit()`], as it could get error
109    /// result if the header is inconsistent with the message.
110    pub fn finalize(&mut self) {
111        self.header.cmd = self.payload.command();
112        self.header.version = self.payload.version();
113    }
114
115    /// Return the resolved family ID which should be filled into the
116    /// `message_type` field in [`NetlinkHeader`].
117    ///
118    /// The implementation of [`NetlinkSerializable::message_type()`] would use
119    /// this function's result as its the return value. Thus, the family id can
120    /// be automatically filled into the `message_type` during the call to
121    /// [`NetlinkMessage::finalize()`].
122    pub fn family_id(&self) -> u16 {
123        let static_id = self.payload.family_id();
124        if static_id == 0 {
125            self.resolved_family_id
126        } else {
127            static_id
128        }
129    }
130}
131
132impl<F> Emitable for GenlMessage<F>
133where
134    F: GenlFamily + Emitable + Debug,
135{
136    fn buffer_len(&self) -> usize {
137        self.header.buffer_len() + self.payload.buffer_len()
138    }
139
140    fn emit(&self, buffer: &mut [u8]) {
141        self.header.emit(buffer);
142
143        let buffer = &mut buffer[self.header.buffer_len()..];
144        self.payload.emit(buffer);
145    }
146}
147
148impl<F> NetlinkSerializable for GenlMessage<F>
149where
150    F: GenlFamily + Emitable + Debug,
151{
152    fn message_type(&self) -> u16 {
153        self.family_id()
154    }
155
156    fn buffer_len(&self) -> usize {
157        <Self as Emitable>::buffer_len(self)
158    }
159
160    fn serialize(&self, buffer: &mut [u8]) {
161        self.emit(buffer)
162    }
163}
164
165impl<F> NetlinkDeserializable for GenlMessage<F>
166where
167    F: ParseableParametrized<[u8], GenlHeader> + Debug,
168{
169    type Error = DecodeError;
170    fn deserialize(
171        header: &NetlinkHeader,
172        payload: &[u8],
173    ) -> Result<Self, Self::Error> {
174        let buffer = GenlBuffer::new_checked(payload)?;
175        GenlMessage::parse_with_param(&buffer, header.message_type)
176    }
177}
178
179impl<F> From<GenlMessage<F>> for NetlinkPayload<GenlMessage<F>>
180where
181    F: Debug,
182{
183    fn from(message: GenlMessage<F>) -> Self {
184        NetlinkPayload::InnerMessage(message)
185    }
186}