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 Errno::EINVAL
203 }
204 DecodeError::FailedToParseNlMsgError(error)
205 | DecodeError::FailedToParseNlMsgDone(error)
206 | DecodeError::FailedToParseMessageWithType { message_type: _, source: error }
207 | DecodeError::FailedToParseNetlinkHeader(error) => decode_error_to_errno(error),
208 }
209}
210
211impl ValidationError {
212 pub fn into_error_message<M: NetlinkSerializable>(self) -> Option<NetlinkMessage<M>> {
215 match self {
216 ValidationError::Parse(ParseError { error, header }) => {
217 let header = header?;
219 Some(netlink_packet::new_error(Err(decode_error_to_errno(&error)), header))
223 }
224 ValidationError::Permission { header, error } => {
225 Some(netlink_packet::new_error(Err(error), header))
226 }
227 }
228 }
229}
230
231#[derive(Clone, Debug)]
233pub struct NetlinkMessageWithCreds<M, C> {
234 message: M,
235 creds: C,
236}
237
238impl<M, C> NetlinkMessageWithCreds<M, C> {
239 pub fn new(message: M, creds: C) -> Self {
241 Self { message, creds }
242 }
243}
244
245pub trait UnvalidatedNetlinkMessage {
249 type Message;
251 type Credentials;
253
254 fn validate_creds_and_get_message<PS: AccessControl<Self::Credentials>>(
258 self,
259 access_control: &PS,
260 ) -> Result<NetlinkMessage<Self::Message>, ValidationError>;
261}
262
263impl<M, C> UnvalidatedNetlinkMessage for NetlinkMessageWithCreds<M, C>
264where
265 M: MaybeParsedNetlinkMessage,
266 M::Message: MessageWithPermission,
267{
268 type Message = M::Message;
269 type Credentials = C;
270
271 fn validate_creds_and_get_message<PS: AccessControl<C>>(
272 self,
273 access_control: &PS,
274 ) -> Result<NetlinkMessage<M::Message>, ValidationError> {
275 let Self { message, creds } = self;
276 let message = message.try_into_parsed().map_err(ValidationError::Parse)?;
277 let permission = match &message.payload {
278 NetlinkPayload::InnerMessage(msg) => msg.permission(),
279 NetlinkPayload::Done(_)
280 | NetlinkPayload::Error(_)
281 | NetlinkPayload::Noop
282 | NetlinkPayload::Overrun(_) => return Ok(message),
283 };
284
285 access_control
286 .grant_assess(&creds, permission)
287 .map_err(|error| ValidationError::Permission { header: message.header, error })?;
288 Ok(message)
289 }
290}
291
292pub trait NetlinkContext {
294 type Creds: Clone + Send + Debug;
296
297 type Sender<M: Clone + NetlinkSerializable + Send>: Sender<M>;
299
300 type Receiver<M: Send + MessageWithPermission + NetlinkDeserializable<Error: Into<DecodeError>>>: Receiver<M, Self::Creds>;
302
303 type AccessControl<'a>: AccessControl<Self::Creds>;
305}
306
307#[cfg(test)]
308pub(crate) mod testutil {
309 use super::*;
310 use crate::mpsc;
311 use futures::{FutureExt as _, StreamExt as _};
312 use netlink_packet_core::NetlinkSerializable;
313
314 #[derive(Clone, Debug, PartialEq, Eq)]
315 pub(crate) struct SentMessage<M> {
316 pub message: NetlinkMessage<M>,
317 pub group: Option<ModernGroup>,
318 }
319
320 impl<M> SentMessage<M> {
321 pub(crate) fn unicast(message: NetlinkMessage<M>) -> Self {
322 Self { message, group: None }
323 }
324
325 pub(crate) fn multicast(message: NetlinkMessage<M>, group: ModernGroup) -> Self {
326 Self { message, group: Some(group) }
327 }
328 }
329
330 #[derive(Clone, Debug)]
331 pub(crate) struct FakeSender<M> {
332 sender: futures::channel::mpsc::UnboundedSender<SentMessage<M>>,
333 }
334
335 impl<M: Clone + Send + NetlinkSerializable> Sender<M> for FakeSender<M> {
336 fn send(&mut self, message: NetlinkMessage<M>, group: Option<ModernGroup>) {
337 self.sender
338 .unbounded_send(SentMessage { message, group })
339 .expect("unable to send message");
340 }
341 }
342
343 pub(crate) struct FakeSenderSink<M> {
344 receiver: futures::channel::mpsc::UnboundedReceiver<SentMessage<M>>,
345 }
346
347 impl<M> FakeSenderSink<M> {
348 pub(crate) fn take_messages(&mut self) -> Vec<SentMessage<M>> {
349 let mut messages = Vec::new();
350 while let Some(msg_opt) = self.receiver.next().now_or_never() {
351 match msg_opt {
352 Some(msg) => messages.push(msg),
353 None => return messages, };
355 }
356 messages
358 }
359
360 pub(crate) async fn next_message(&mut self) -> SentMessage<M> {
361 self.receiver.next().await.expect("receiver unexpectedly closed")
362 }
363 }
364
365 pub(crate) fn fake_sender_with_sink<M>() -> (FakeSender<M>, FakeSenderSink<M>) {
366 let (sender, receiver) = futures::channel::mpsc::unbounded();
367 (FakeSender { sender }, FakeSenderSink { receiver })
368 }
369
370 #[derive(Default, Debug, Clone)]
371 pub(crate) struct FakeCreds {
372 error: Option<Errno>,
373 }
374
375 impl FakeCreds {
376 pub fn with_error(error: Errno) -> Self {
377 FakeCreds { error: Some(error) }
378 }
379 }
380
381 #[derive(Default, Clone)]
382 pub(crate) struct FakeAccessControl {}
383
384 impl AccessControl<FakeCreds> for FakeAccessControl {
385 fn grant_assess(&self, creds: &FakeCreds, _perm: Permission) -> Result<(), Errno> {
386 if let Some(ref error) = creds.error { Err(*error) } else { Ok(()) }
387 }
388 }
389
390 pub(crate) struct TestNetlinkContext;
391
392 impl NetlinkContext for TestNetlinkContext {
393 type Creds = FakeCreds;
394 type Sender<M: Clone + NetlinkSerializable + Send> = FakeSender<M>;
395 type Receiver<
396 M: Send + MessageWithPermission + NetlinkDeserializable<Error: Into<DecodeError>>,
397 > = mpsc::Receiver<NetlinkMessageWithCreds<NetlinkMessage<M>, Self::Creds>>;
398 type AccessControl<'a> = FakeAccessControl;
399 }
400}