1use futures::Stream;
8use netlink_packet_core::{
9 NetlinkBuffer, NetlinkDeserializable, NetlinkHeader, NetlinkMessage, NetlinkPayload,
10 NetlinkSerializable,
11};
12use netlink_packet_route::RouteNetlinkMessageParseError;
13use netlink_packet_utils::nla::NlaError;
14use netlink_packet_utils::{DecodeError, Parseable};
15use std::fmt::Debug;
16
17use crate::multicast_groups::ModernGroup;
18use crate::netlink_packet;
19use crate::netlink_packet::errno::Errno;
20
21pub trait Sender<M>: Clone + Send + Sync {
23 fn send(&mut self, message: NetlinkMessage<M>, group: Option<ModernGroup>);
30}
31
32pub trait Receiver<M, C>:
36 Stream<Item: UnvalidatedNetlinkMessage<Message = M, Credentials = C>> + Send
37where
38 M: Send + MessageWithPermission,
39 C: Send,
40{
41}
42
43impl<M, C, S> Receiver<M, C> for S
45where
46 M: Send + MessageWithPermission,
47 C: Send,
48 S: Stream<Item: UnvalidatedNetlinkMessage<Message = M, Credentials = C>> + Send,
49{
50}
51
52pub enum Permission {
55 NetlinkRouteRead,
57
58 NetlinkRouteWrite,
60}
61
62pub trait AccessControl<C>: Clone {
64 fn grant_assess(&self, creds: &C, permission: Permission) -> Result<(), Errno>;
67}
68
69pub trait MessageWithPermission {
72 fn permission(&self) -> Permission;
74}
75
76#[derive(Debug)]
78pub struct ParseError {
79 pub error: DecodeError,
81 pub header: Option<NetlinkHeader>,
86}
87
88pub trait MaybeParsedNetlinkMessage {
91 type Message: MessageWithPermission;
93
94 fn try_into_parsed(self) -> Result<NetlinkMessage<Self::Message>, ParseError>;
96}
97
98impl<M: MessageWithPermission> MaybeParsedNetlinkMessage for NetlinkMessage<M> {
99 type Message = M;
100 fn try_into_parsed(self) -> Result<NetlinkMessage<M>, ParseError> {
101 Ok(self)
102 }
103}
104
105pub struct UnparsedNetlinkMessage<B, M> {
107 data: B,
108 _marker: std::marker::PhantomData<M>,
109}
110
111impl<B, M> UnparsedNetlinkMessage<B, M> {
112 pub fn new(data: B) -> Self {
114 Self { data, _marker: std::marker::PhantomData }
115 }
116}
117
118impl<M, B> MaybeParsedNetlinkMessage for UnparsedNetlinkMessage<B, M>
119where
120 B: AsRef<[u8]>,
121 M: NetlinkDeserializable + MessageWithPermission,
122 M::Error: Into<DecodeError>,
123{
124 type Message = M;
125
126 fn try_into_parsed(self) -> Result<NetlinkMessage<M>, ParseError> {
127 let Self { data, _marker } = self;
128 let data = data.as_ref();
129 let netlink_buffer =
130 NetlinkBuffer::new(&data).map_err(|error| ParseError { error, header: None })?;
131 NetlinkMessage::<M>::parse(&netlink_buffer).map_err(|error| ParseError {
132 error,
133 header: NetlinkHeader::parse(&netlink_buffer).ok(),
136 })
137 }
138}
139
140#[derive(Debug)]
142#[allow(missing_docs)]
143pub enum ValidationError {
144 Parse(ParseError),
146 Permission { header: NetlinkHeader, error: Errno },
148}
149
150fn nla_error_to_errno(error: &NlaError) -> Errno {
153 match error {
154 NlaError::BufferTooSmall { .. }
155 | NlaError::LengthMismatch { .. }
156 | NlaError::InvalidLength { .. } => Errno::EINVAL,
157 }
158}
159
160fn route_netlink_error_to_errno(error: &RouteNetlinkMessageParseError) -> Errno {
163 match error {
164 RouteNetlinkMessageParseError::ParseBuffer(decode_error)
165 | RouteNetlinkMessageParseError::InvalidLinkMessage(decode_error) => {
166 decode_error_to_errno(decode_error)
167 }
168 RouteNetlinkMessageParseError::InvalidRouteMessage(_)
169 | RouteNetlinkMessageParseError::InvalidAddrMessage(_)
170 | RouteNetlinkMessageParseError::InvalidPrefixMessage(_)
171 | RouteNetlinkMessageParseError::InvalidFibRuleMessage(_)
172 | RouteNetlinkMessageParseError::InvalidTcMessage(_)
173 | RouteNetlinkMessageParseError::InvalidNsidMessage(_)
174 | RouteNetlinkMessageParseError::InvalidNeighbourMessage(_)
175 | RouteNetlinkMessageParseError::InvalidNeighbourTableMessage(_)
176 | RouteNetlinkMessageParseError::InvalidNeighbourDiscoveryUserOptionMessage(_) => {
177 Errno::EINVAL
178 }
179 RouteNetlinkMessageParseError::UnknownMessageType(_) => Errno::ENOTSUP,
180 }
181}
182
183fn decode_error_to_errno(error: &DecodeError) -> Errno {
186 match error {
187 DecodeError::InvalidMACAddress
188 | DecodeError::InvalidIPAddress
189 | DecodeError::Utf8Error(_)
190 | DecodeError::InvalidU8
191 | DecodeError::InvalidU16
192 | DecodeError::InvalidU32
193 | DecodeError::InvalidU64
194 | DecodeError::InvalidU128
195 | DecodeError::InvalidI32
196 | DecodeError::InvalidBufferLength { .. } => Errno::EINVAL,
197 DecodeError::Nla(nla_error) => nla_error_to_errno(nla_error),
198 DecodeError::Other(error) => {
199 if let Some(error) = error.downcast_ref::<RouteNetlinkMessageParseError>() {
200 return route_netlink_error_to_errno(error);
201 }
202 if let Some(error) = error.downcast_ref::<netlink_packet_utils::DecodeError>() {
203 return decode_error_to_errno(error);
204 }
205 Errno::EINVAL
206 }
207 DecodeError::FailedToParseNlMsgError(error)
208 | DecodeError::FailedToParseNlMsgDone(error)
209 | DecodeError::FailedToParseMessageWithType { message_type: _, source: error }
210 | DecodeError::FailedToParseNetlinkHeader(error) => decode_error_to_errno(error),
211 }
212}
213
214impl ValidationError {
215 pub fn into_error_message<M: NetlinkSerializable>(self) -> Option<NetlinkMessage<M>> {
218 match self {
219 ValidationError::Parse(ParseError { error, header }) => {
220 let header = header?;
222 Some(netlink_packet::new_error(Err(decode_error_to_errno(&error)), header))
226 }
227 ValidationError::Permission { header, error } => {
228 Some(netlink_packet::new_error(Err(error), header))
229 }
230 }
231 }
232}
233
234#[derive(Clone, Debug)]
236pub struct NetlinkMessageWithCreds<M, C> {
237 message: M,
238 creds: C,
239}
240
241impl<M, C> NetlinkMessageWithCreds<M, C> {
242 pub fn new(message: M, creds: C) -> Self {
244 Self { message, creds }
245 }
246}
247
248pub trait UnvalidatedNetlinkMessage {
252 type Message;
254 type Credentials;
256
257 fn validate_creds_and_get_message<PS: AccessControl<Self::Credentials>>(
261 self,
262 access_control: &PS,
263 ) -> Result<NetlinkMessage<Self::Message>, ValidationError>;
264}
265
266impl<M, C> UnvalidatedNetlinkMessage for NetlinkMessageWithCreds<M, C>
267where
268 M: MaybeParsedNetlinkMessage,
269 M::Message: MessageWithPermission,
270{
271 type Message = M::Message;
272 type Credentials = C;
273
274 fn validate_creds_and_get_message<PS: AccessControl<C>>(
275 self,
276 access_control: &PS,
277 ) -> Result<NetlinkMessage<M::Message>, ValidationError> {
278 let Self { message, creds } = self;
279 let message = message.try_into_parsed().map_err(ValidationError::Parse)?;
280 let permission = match &message.payload {
281 NetlinkPayload::InnerMessage(msg) => msg.permission(),
282 NetlinkPayload::Done(_)
283 | NetlinkPayload::Error(_)
284 | NetlinkPayload::Noop
285 | NetlinkPayload::Overrun(_) => return Ok(message),
286 };
287
288 access_control
289 .grant_assess(&creds, permission)
290 .map_err(|error| ValidationError::Permission { header: message.header, error })?;
291 Ok(message)
292 }
293}
294
295pub trait NetlinkContext {
297 type Creds: Clone + Send + Debug;
299
300 type Sender<M: Clone + NetlinkSerializable + Send>: Sender<M>;
302
303 type Receiver<M: Send + MessageWithPermission + NetlinkDeserializable<Error: Into<DecodeError>>>: Receiver<M, Self::Creds>;
305
306 type AccessControl<'a>: AccessControl<Self::Creds>;
308}
309
310#[cfg(test)]
311pub(crate) mod testutil {
312 use super::*;
313 use crate::mpsc;
314 use futures::{FutureExt as _, StreamExt as _};
315 use netlink_packet_core::NetlinkSerializable;
316
317 #[derive(Clone, Debug, PartialEq, Eq)]
318 pub(crate) struct SentMessage<M> {
319 pub message: NetlinkMessage<M>,
320 pub group: Option<ModernGroup>,
321 }
322
323 impl<M> SentMessage<M> {
324 pub(crate) fn unicast(message: NetlinkMessage<M>) -> Self {
325 Self { message, group: None }
326 }
327
328 pub(crate) fn multicast(message: NetlinkMessage<M>, group: ModernGroup) -> Self {
329 Self { message, group: Some(group) }
330 }
331 }
332
333 #[derive(Clone, Debug)]
334 pub(crate) struct FakeSender<M> {
335 sender: futures::channel::mpsc::UnboundedSender<SentMessage<M>>,
336 }
337
338 impl<M: Clone + Send + NetlinkSerializable> Sender<M> for FakeSender<M> {
339 fn send(&mut self, message: NetlinkMessage<M>, group: Option<ModernGroup>) {
340 self.sender
341 .unbounded_send(SentMessage { message, group })
342 .expect("unable to send message");
343 }
344 }
345
346 pub(crate) struct FakeSenderSink<M> {
347 receiver: futures::channel::mpsc::UnboundedReceiver<SentMessage<M>>,
348 }
349
350 impl<M> FakeSenderSink<M> {
351 pub(crate) fn take_messages(&mut self) -> Vec<SentMessage<M>> {
352 let mut messages = Vec::new();
353 while let Some(msg_opt) = self.receiver.next().now_or_never() {
354 match msg_opt {
355 Some(msg) => messages.push(msg),
356 None => return messages, };
358 }
359 messages
361 }
362
363 pub(crate) async fn next_message(&mut self) -> SentMessage<M> {
364 self.receiver.next().await.expect("receiver unexpectedly closed")
365 }
366 }
367
368 pub(crate) fn fake_sender_with_sink<M>() -> (FakeSender<M>, FakeSenderSink<M>) {
369 let (sender, receiver) = futures::channel::mpsc::unbounded();
370 (FakeSender { sender }, FakeSenderSink { receiver })
371 }
372
373 #[derive(Default, Debug, Clone)]
374 pub(crate) struct FakeCreds {
375 error: Option<Errno>,
376 }
377
378 impl FakeCreds {
379 pub fn with_error(error: Errno) -> Self {
380 FakeCreds { error: Some(error) }
381 }
382 }
383
384 #[derive(Default, Clone)]
385 pub(crate) struct FakeAccessControl {}
386
387 impl AccessControl<FakeCreds> for FakeAccessControl {
388 fn grant_assess(&self, creds: &FakeCreds, _perm: Permission) -> Result<(), Errno> {
389 if let Some(ref error) = creds.error { Err(*error) } else { Ok(()) }
390 }
391 }
392
393 pub(crate) struct TestNetlinkContext;
394
395 impl NetlinkContext for TestNetlinkContext {
396 type Creds = FakeCreds;
397 type Sender<M: Clone + NetlinkSerializable + Send> = FakeSender<M>;
398 type Receiver<
399 M: Send + MessageWithPermission + NetlinkDeserializable<Error: Into<DecodeError>>,
400 > = mpsc::Receiver<NetlinkMessageWithCreds<NetlinkMessage<M>, Self::Creds>>;
401 type AccessControl<'a> = FakeAccessControl;
402 }
403}