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