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}