Skip to main content

netlink_packet_route/
message.rs

1// SPDX-License-Identifier: MIT
2
3use crate::AddressFamily;
4use crate::address::{AddressError, AddressHeader, AddressMessage, AddressMessageBuffer};
5use crate::link::{LinkAttribute, LinkExtentMask, LinkHeader, LinkMessage, LinkMessageBuffer};
6use crate::neighbour::{NeighbourError, NeighbourMessage, NeighbourMessageBuffer};
7use crate::neighbour_discovery_user_option::{
8    NeighbourDiscoveryUserOptionError, NeighbourDiscoveryUserOptionMessage,
9    NeighbourDiscoveryUserOptionMessageBuffer,
10};
11use crate::neighbour_table::{
12    NeighbourTableError, NeighbourTableMessage, NeighbourTableMessageBuffer,
13};
14use crate::nsid::{NsidError, NsidMessage, NsidMessageBuffer};
15use crate::prefix::{PrefixError, PrefixMessage, PrefixMessageBuffer};
16use crate::route::{RouteError, RouteHeader, RouteMessage, RouteMessageBuffer};
17use crate::rule::{RuleError, RuleMessage, RuleMessageBuffer};
18use crate::tc::{TcError, TcMessage, TcMessageBuffer};
19use netlink_packet_core::{
20    NetlinkDeserializable, NetlinkHeader, NetlinkPayload, NetlinkSerializable,
21};
22use netlink_packet_utils::{DecodeError, Emitable, Parseable, ParseableParametrized};
23use thiserror::Error;
24
25const RTM_NEWLINK: u16 = 16;
26const RTM_DELLINK: u16 = 17;
27const RTM_GETLINK: u16 = 18;
28const RTM_SETLINK: u16 = 19;
29const RTM_NEWADDR: u16 = 20;
30const RTM_DELADDR: u16 = 21;
31const RTM_GETADDR: u16 = 22;
32const RTM_NEWROUTE: u16 = 24;
33const RTM_DELROUTE: u16 = 25;
34const RTM_GETROUTE: u16 = 26;
35const RTM_NEWNEIGH: u16 = 28;
36const RTM_DELNEIGH: u16 = 29;
37const RTM_GETNEIGH: u16 = 30;
38const RTM_NEWRULE: u16 = 32;
39const RTM_DELRULE: u16 = 33;
40const RTM_GETRULE: u16 = 34;
41const RTM_NEWQDISC: u16 = 36;
42const RTM_DELQDISC: u16 = 37;
43const RTM_GETQDISC: u16 = 38;
44const RTM_NEWTCLASS: u16 = 40;
45const RTM_DELTCLASS: u16 = 41;
46const RTM_GETTCLASS: u16 = 42;
47const RTM_NEWTFILTER: u16 = 44;
48const RTM_DELTFILTER: u16 = 45;
49const RTM_GETTFILTER: u16 = 46;
50// const RTM_NEWACTION: u16 = 48;
51// const RTM_DELACTION: u16 = 49;
52// const RTM_GETACTION: u16 = 50;
53const RTM_NEWPREFIX: u16 = 52;
54// const RTM_GETMULTICAST: u16 = 58;
55// const RTM_GETANYCAST: u16 = 62;
56const RTM_NEWNEIGHTBL: u16 = 64;
57const RTM_GETNEIGHTBL: u16 = 66;
58const RTM_SETNEIGHTBL: u16 = 67;
59const RTM_NEWNDUSEROPT: u16 = 68;
60// const RTM_NEWADDRLABEL: u16 = 72;
61// const RTM_DELADDRLABEL: u16 = 73;
62// const RTM_GETADDRLABEL: u16 = 74;
63// const RTM_GETDCB: u16 = 78;
64// const RTM_SETDCB: u16 = 79;
65// const RTM_NEWNETCONF: u16 = 80;
66// const RTM_DELNETCONF: u16 = 81;
67// const RTM_GETNETCONF: u16 = 82;
68// const RTM_NEWMDB: u16 = 84;
69// const RTM_DELMDB: u16 = 85;
70// const RTM_GETMDB: u16 = 86;
71const RTM_NEWNSID: u16 = 88;
72const RTM_DELNSID: u16 = 89;
73const RTM_GETNSID: u16 = 90;
74// const RTM_NEWSTATS: u16 = 92;
75// const RTM_GETSTATS: u16 = 94;
76// const RTM_NEWCACHEREPORT: u16 = 96;
77const RTM_NEWCHAIN: u16 = 100;
78const RTM_DELCHAIN: u16 = 101;
79const RTM_GETCHAIN: u16 = 102;
80const RTM_NEWLINKPROP: u16 = 108;
81const RTM_DELLINKPROP: u16 = 109;
82
83buffer!(RouteNetlinkMessageBuffer);
84
85#[derive(Debug, Error)]
86pub enum RouteNetlinkMessageParseError {
87    #[error("Invalid link message")]
88    InvalidLinkMessage(#[source] DecodeError),
89
90    #[error(transparent)]
91    InvalidRouteMessage(#[from] RouteError),
92
93    #[error(transparent)]
94    InvalidAddrMessage(#[from] AddressError),
95
96    #[error(transparent)]
97    InvalidPrefixMessage(#[from] PrefixError),
98
99    #[error(transparent)]
100    InvalidFibRuleMessage(#[from] RuleError),
101
102    #[error(transparent)]
103    InvalidTcMessage(#[from] TcError),
104
105    #[error(transparent)]
106    InvalidNsidMessage(#[from] NsidError),
107
108    #[error(transparent)]
109    InvalidNeighbourMessage(#[from] NeighbourError),
110
111    #[error(transparent)]
112    InvalidNeighbourTableMessage(#[from] NeighbourTableError),
113
114    #[error(transparent)]
115    InvalidNeighbourDiscoveryUserOptionMessage(#[from] NeighbourDiscoveryUserOptionError),
116
117    #[error("Unknown message type: {0}")]
118    UnknownMessageType(u16),
119
120    #[error("Parse buffer: {0}")]
121    ParseBuffer(#[source] DecodeError),
122}
123
124impl From<RouteNetlinkMessageParseError> for DecodeError {
125    fn from(e: RouteNetlinkMessageParseError) -> Self {
126        DecodeError::Other(e.into())
127    }
128}
129
130// HACK: prior to sometime in October 2018, iproute2 would send dump requests
131// for a number of object types, including `addr`, `route`, and `rule`, that
132// incorrectly used the interface message header and attributes.
133//
134// https://github.com/iproute2/iproute2/commit/b05d9a3d5866219b3c772256dc215bb04e65baa5
135// is an example of a commit that fixed this bug, and
136// https://github.com/iproute2/iproute2/blob/b05d9a3d5866219b3c772256dc215bb04e65baa5/lib/libnetlink.c#L301-L327
137// shows the problematic function(s) in question.
138//
139// These requests succeed on Linux if strict checking is not enabled because the
140// address family appears in the correct byte and the rest of the header is
141// zeroed out.
142//
143// In order to allow these requests to succeed in Starnix as well, this function
144// explicitly checks if the malformed request format is present and returns the
145// address family if so.
146//
147// TODO(https://fxbug.dev/456508664): Remove this hack once
148// `NETLINK_GET_STRICT_CHK` (or rather, its absence) is properly supported.
149fn looks_like_bad_iproute2_dump_req<'a, T: AsRef<[u8]> + ?Sized>(
150    buf: &RouteNetlinkMessageBuffer<&'a T>,
151) -> Option<AddressFamily> {
152    let buf_inner = buf.inner();
153    let buffer = LinkMessageBuffer::new(&buf_inner).ok()?;
154    let as_link_msg = LinkMessage::parse(&buffer).ok()?;
155
156    // The format of a malformed request is an `RTM_GETLINK` message where:
157    // * all header fields are unset except for the address family (which is the
158    // address family of the intended request); and
159    // * the sole attribute sets `IFLA_EXT_MASK` to `RTEXT_FILTER_VF`.
160    let bad_req_format = LinkMessage {
161        header: LinkHeader {
162            interface_family: as_link_msg.header.interface_family,
163            ..Default::default()
164        },
165        attributes: vec![LinkAttribute::ExtMask(vec![LinkExtentMask::Vf])],
166        ..Default::default()
167    };
168    (as_link_msg == bad_req_format).then_some(as_link_msg.header.interface_family)
169}
170
171impl<'a, T: AsRef<[u8]> + ?Sized> ParseableParametrized<RouteNetlinkMessageBuffer<&'a T>, u16>
172    for RouteNetlinkMessage
173{
174    type Error = RouteNetlinkMessageParseError;
175
176    fn parse_with_param(
177        buf: &RouteNetlinkMessageBuffer<&'a T>,
178        message_type: u16,
179    ) -> Result<Self, Self::Error> {
180        let message = match message_type {
181            // Link messages
182            RTM_NEWLINK | RTM_GETLINK | RTM_DELLINK | RTM_SETLINK => {
183                let msg = match LinkMessageBuffer::new(&buf.inner()) {
184                    Ok(buf) => LinkMessage::parse(&buf)
185                        .map_err(RouteNetlinkMessageParseError::InvalidLinkMessage)?,
186                    // HACK: iproute2 sends invalid RTM_GETLINK message, where
187                    // the header is limited to the
188                    // interface family (1 byte) and 3 bytes of padding.
189                    Err(e) => {
190                        if buf.inner().len() == 4 && message_type == RTM_GETLINK {
191                            let mut msg = LinkMessage::default();
192                            msg.header.interface_family = buf.inner()[0].into();
193                            msg
194                        } else {
195                            return Err(RouteNetlinkMessageParseError::InvalidLinkMessage(e));
196                        }
197                    }
198                };
199                match message_type {
200                    RTM_NEWLINK => RouteNetlinkMessage::NewLink(msg),
201                    RTM_GETLINK => RouteNetlinkMessage::GetLink(msg),
202                    RTM_DELLINK => RouteNetlinkMessage::DelLink(msg),
203                    RTM_SETLINK => RouteNetlinkMessage::SetLink(msg),
204                    _ => unreachable!(),
205                }
206            }
207
208            // Address messages
209            RTM_NEWADDR | RTM_GETADDR | RTM_DELADDR => {
210                let msg = match AddressMessageBuffer::new(&buf.inner()) {
211                    Ok(buffer) => AddressMessage::parse(&buffer).or_else(|e| {
212                        if message_type == RTM_GETADDR
213                            && let Some(af) = looks_like_bad_iproute2_dump_req(buf)
214                        {
215                            let mut message = AddressMessage::default();
216                            message.header.family = af.into();
217                            return Ok(message);
218                        }
219                        Err(e)
220                    })?,
221                    // HACK: iproute2 sends invalid RTM_GETADDR message, where
222                    // the header is limited to the
223                    // interface family (1 byte) and 3 bytes of padding.
224                    Err(e) => {
225                        if buf.inner().len() == 4 && message_type == RTM_GETADDR {
226                            let mut msg = AddressMessage {
227                                header: AddressHeader::default(),
228                                attributes: vec![],
229                            };
230                            msg.header.family = buf.inner()[0].into();
231                            msg
232                        } else {
233                            return Err(RouteNetlinkMessageParseError::InvalidAddrMessage(
234                                AddressError::FailedBufferInit(e),
235                            ));
236                        }
237                    }
238                };
239                match message_type {
240                    RTM_NEWADDR => RouteNetlinkMessage::NewAddress(msg),
241                    RTM_GETADDR => RouteNetlinkMessage::GetAddress(msg),
242                    RTM_DELADDR => RouteNetlinkMessage::DelAddress(msg),
243                    _ => unreachable!(),
244                }
245            }
246
247            // Neighbour messages
248            RTM_NEWNEIGH | RTM_GETNEIGH | RTM_DELNEIGH => {
249                let buf_inner = buf.inner();
250                let buffer = NeighbourMessageBuffer::new(&buf_inner)
251                    .map_err(RouteNetlinkMessageParseError::ParseBuffer)?;
252                let msg = NeighbourMessage::parse(&buffer)?;
253                match message_type {
254                    RTM_GETNEIGH => RouteNetlinkMessage::GetNeighbour(msg),
255                    RTM_NEWNEIGH => RouteNetlinkMessage::NewNeighbour(msg),
256                    RTM_DELNEIGH => RouteNetlinkMessage::DelNeighbour(msg),
257                    _ => unreachable!(),
258                }
259            }
260
261            // Neighbour table messages
262            RTM_NEWNEIGHTBL | RTM_GETNEIGHTBL | RTM_SETNEIGHTBL => {
263                let buf_inner = buf.inner();
264                let buffer = NeighbourTableMessageBuffer::new(&buf_inner)
265                    .map_err(RouteNetlinkMessageParseError::ParseBuffer)?;
266                let msg = NeighbourTableMessage::parse(&buffer)
267                    .map_err(RouteNetlinkMessageParseError::InvalidNeighbourTableMessage)?;
268                match message_type {
269                    RTM_GETNEIGHTBL => RouteNetlinkMessage::GetNeighbourTable(msg),
270                    RTM_NEWNEIGHTBL => RouteNetlinkMessage::NewNeighbourTable(msg),
271                    RTM_SETNEIGHTBL => RouteNetlinkMessage::SetNeighbourTable(msg),
272                    _ => unreachable!(),
273                }
274            }
275
276            RTM_NEWNDUSEROPT => {
277                let msg = NeighbourDiscoveryUserOptionMessage::parse(
278                    &NeighbourDiscoveryUserOptionMessageBuffer::new(&buf.inner())
279                        .map_err(NeighbourDiscoveryUserOptionError::ParseBuffer)?,
280                )?;
281                RouteNetlinkMessage::NewNeighbourDiscoveryUserOption(msg)
282            }
283
284            // Route messages
285            RTM_NEWROUTE | RTM_GETROUTE | RTM_DELROUTE => {
286                let msg = match RouteMessageBuffer::new(&buf.inner()) {
287                    Ok(buffer) => RouteMessage::parse(&buffer).or_else(|e| {
288                        if message_type == RTM_GETROUTE
289                            && let Some(af) = looks_like_bad_iproute2_dump_req(buf)
290                        {
291                            let mut message = RouteMessage::default();
292                            message.header.address_family = af;
293                            return Ok(message);
294                        }
295                        Err(e)
296                    })?,
297                    // HACK: iproute2 sends invalid RTM_GETROUTE message, where
298                    // the header is limited to the
299                    // interface family (1 byte) and 3 bytes of padding.
300                    Err(e) => {
301                        // Not only does iproute2 sends invalid messages, it's
302                        // also inconsistent in
303                        // doing so: for link and address messages, the length
304                        // advertised in the
305                        // netlink header includes the 3 bytes of padding but it
306                        // does not seem to be the case
307                        // for the route message, hence the buf.length() == 1
308                        // check.
309                        if (buf.inner().len() == 4 || buf.inner().len() == 1)
310                            && message_type == RTM_GETROUTE
311                        {
312                            let mut msg =
313                                RouteMessage { header: RouteHeader::default(), attributes: vec![] };
314                            msg.header.address_family = buf.inner()[0].into();
315                            msg
316                        } else {
317                            return Err(RouteNetlinkMessageParseError::ParseBuffer(e));
318                        }
319                    }
320                };
321                match message_type {
322                    RTM_NEWROUTE => RouteNetlinkMessage::NewRoute(msg),
323                    RTM_GETROUTE => RouteNetlinkMessage::GetRoute(msg),
324                    RTM_DELROUTE => RouteNetlinkMessage::DelRoute(msg),
325                    _ => unreachable!(),
326                }
327            }
328
329            // Prefix messages
330            RTM_NEWPREFIX => {
331                let buf_inner = buf.inner();
332                let buffer = PrefixMessageBuffer::new(&buf_inner)
333                    .map_err(RouteNetlinkMessageParseError::ParseBuffer)?;
334                RouteNetlinkMessage::NewPrefix(PrefixMessage::parse(&buffer)?)
335            }
336            RTM_NEWRULE | RTM_GETRULE | RTM_DELRULE => {
337                let buf_inner = buf.inner();
338                let buffer = RuleMessageBuffer::new(&buf_inner)
339                    .map_err(RouteNetlinkMessageParseError::ParseBuffer)?;
340                let msg = RuleMessage::parse(&buffer).or_else(|e| {
341                    if message_type == RTM_GETRULE
342                        && let Some(af) = looks_like_bad_iproute2_dump_req(buf)
343                    {
344                        let mut message = RuleMessage::default();
345                        message.header.family = af;
346                        return Ok(message);
347                    }
348                    Err(e)
349                })?;
350                match message_type {
351                    RTM_NEWRULE => RouteNetlinkMessage::NewRule(msg),
352                    RTM_DELRULE => RouteNetlinkMessage::DelRule(msg),
353                    RTM_GETRULE => RouteNetlinkMessage::GetRule(msg),
354                    _ => unreachable!(),
355                }
356            }
357            // TC Messages
358            RTM_NEWQDISC | RTM_DELQDISC | RTM_GETQDISC | RTM_NEWTCLASS | RTM_DELTCLASS
359            | RTM_GETTCLASS | RTM_NEWTFILTER | RTM_DELTFILTER | RTM_GETTFILTER | RTM_NEWCHAIN
360            | RTM_DELCHAIN | RTM_GETCHAIN => {
361                let buf_inner = buf.inner();
362                let buffer = TcMessageBuffer::new(&buf_inner)
363                    .map_err(RouteNetlinkMessageParseError::ParseBuffer)?;
364                let msg = TcMessage::parse(&buffer)?;
365                match message_type {
366                    RTM_NEWQDISC => RouteNetlinkMessage::NewQueueDiscipline(msg),
367                    RTM_DELQDISC => RouteNetlinkMessage::DelQueueDiscipline(msg),
368                    RTM_GETQDISC => RouteNetlinkMessage::GetQueueDiscipline(msg),
369                    RTM_NEWTCLASS => RouteNetlinkMessage::NewTrafficClass(msg),
370                    RTM_DELTCLASS => RouteNetlinkMessage::DelTrafficClass(msg),
371                    RTM_GETTCLASS => RouteNetlinkMessage::GetTrafficClass(msg),
372                    RTM_NEWTFILTER => RouteNetlinkMessage::NewTrafficFilter(msg),
373                    RTM_DELTFILTER => RouteNetlinkMessage::DelTrafficFilter(msg),
374                    RTM_GETTFILTER => RouteNetlinkMessage::GetTrafficFilter(msg),
375                    RTM_NEWCHAIN => RouteNetlinkMessage::NewTrafficChain(msg),
376                    RTM_DELCHAIN => RouteNetlinkMessage::DelTrafficChain(msg),
377                    RTM_GETCHAIN => RouteNetlinkMessage::GetTrafficChain(msg),
378                    _ => unreachable!(),
379                }
380            }
381
382            // ND ID Messages
383            RTM_NEWNSID | RTM_GETNSID | RTM_DELNSID => {
384                let buf_inner = buf.inner();
385                let buffer = NsidMessageBuffer::new(&buf_inner)
386                    .map_err(RouteNetlinkMessageParseError::ParseBuffer)?;
387                let msg = NsidMessage::parse(&buffer)?;
388                match message_type {
389                    RTM_NEWNSID => RouteNetlinkMessage::NewNsId(msg),
390                    RTM_DELNSID => RouteNetlinkMessage::DelNsId(msg),
391                    RTM_GETNSID => RouteNetlinkMessage::GetNsId(msg),
392                    _ => unreachable!(),
393                }
394            }
395
396            _ => return Err(RouteNetlinkMessageParseError::UnknownMessageType(message_type)),
397        };
398        Ok(message)
399    }
400}
401
402#[derive(Debug, PartialEq, Eq, Clone)]
403pub enum RouteNetlinkMessage {
404    NewLink(LinkMessage),
405    DelLink(LinkMessage),
406    GetLink(LinkMessage),
407    SetLink(LinkMessage),
408    NewLinkProp(LinkMessage),
409    DelLinkProp(LinkMessage),
410    NewAddress(AddressMessage),
411    DelAddress(AddressMessage),
412    GetAddress(AddressMessage),
413    NewNeighbour(NeighbourMessage),
414    GetNeighbour(NeighbourMessage),
415    DelNeighbour(NeighbourMessage),
416    NewNeighbourTable(NeighbourTableMessage),
417    GetNeighbourTable(NeighbourTableMessage),
418    SetNeighbourTable(NeighbourTableMessage),
419    NewNeighbourDiscoveryUserOption(NeighbourDiscoveryUserOptionMessage),
420    NewRoute(RouteMessage),
421    DelRoute(RouteMessage),
422    GetRoute(RouteMessage),
423    NewPrefix(PrefixMessage),
424    NewQueueDiscipline(TcMessage),
425    DelQueueDiscipline(TcMessage),
426    GetQueueDiscipline(TcMessage),
427    NewTrafficClass(TcMessage),
428    DelTrafficClass(TcMessage),
429    GetTrafficClass(TcMessage),
430    NewTrafficFilter(TcMessage),
431    DelTrafficFilter(TcMessage),
432    GetTrafficFilter(TcMessage),
433    NewTrafficChain(TcMessage),
434    DelTrafficChain(TcMessage),
435    GetTrafficChain(TcMessage),
436    NewNsId(NsidMessage),
437    DelNsId(NsidMessage),
438    GetNsId(NsidMessage),
439    NewRule(RuleMessage),
440    DelRule(RuleMessage),
441    GetRule(RuleMessage),
442}
443
444impl RouteNetlinkMessage {
445    pub fn is_new_link(&self) -> bool {
446        matches!(self, RouteNetlinkMessage::NewLink(_))
447    }
448
449    pub fn is_del_link(&self) -> bool {
450        matches!(self, RouteNetlinkMessage::DelLink(_))
451    }
452
453    pub fn is_get_link(&self) -> bool {
454        matches!(self, RouteNetlinkMessage::GetLink(_))
455    }
456
457    pub fn is_set_link(&self) -> bool {
458        matches!(self, RouteNetlinkMessage::SetLink(_))
459    }
460
461    pub fn is_new_address(&self) -> bool {
462        matches!(self, RouteNetlinkMessage::NewAddress(_))
463    }
464
465    pub fn is_del_address(&self) -> bool {
466        matches!(self, RouteNetlinkMessage::DelAddress(_))
467    }
468
469    pub fn is_get_address(&self) -> bool {
470        matches!(self, RouteNetlinkMessage::GetAddress(_))
471    }
472
473    pub fn is_get_neighbour(&self) -> bool {
474        matches!(self, RouteNetlinkMessage::GetNeighbour(_))
475    }
476
477    pub fn is_new_route(&self) -> bool {
478        matches!(self, RouteNetlinkMessage::NewRoute(_))
479    }
480
481    pub fn is_new_neighbour(&self) -> bool {
482        matches!(self, RouteNetlinkMessage::NewNeighbour(_))
483    }
484
485    pub fn is_get_route(&self) -> bool {
486        matches!(self, RouteNetlinkMessage::GetRoute(_))
487    }
488
489    pub fn is_del_neighbour(&self) -> bool {
490        matches!(self, RouteNetlinkMessage::DelNeighbour(_))
491    }
492
493    pub fn is_new_neighbour_table(&self) -> bool {
494        matches!(self, RouteNetlinkMessage::NewNeighbourTable(_))
495    }
496
497    pub fn is_get_neighbour_table(&self) -> bool {
498        matches!(self, RouteNetlinkMessage::GetNeighbourTable(_))
499    }
500
501    pub fn is_set_neighbour_table(&self) -> bool {
502        matches!(self, RouteNetlinkMessage::SetNeighbourTable(_))
503    }
504
505    pub fn is_del_route(&self) -> bool {
506        matches!(self, RouteNetlinkMessage::DelRoute(_))
507    }
508
509    pub fn is_new_qdisc(&self) -> bool {
510        matches!(self, RouteNetlinkMessage::NewQueueDiscipline(_))
511    }
512
513    pub fn is_del_qdisc(&self) -> bool {
514        matches!(self, RouteNetlinkMessage::DelQueueDiscipline(_))
515    }
516
517    pub fn is_get_qdisc(&self) -> bool {
518        matches!(self, RouteNetlinkMessage::GetQueueDiscipline(_))
519    }
520
521    pub fn is_new_class(&self) -> bool {
522        matches!(self, RouteNetlinkMessage::NewTrafficClass(_))
523    }
524
525    pub fn is_del_class(&self) -> bool {
526        matches!(self, RouteNetlinkMessage::DelTrafficClass(_))
527    }
528
529    pub fn is_get_class(&self) -> bool {
530        matches!(self, RouteNetlinkMessage::GetTrafficClass(_))
531    }
532
533    pub fn is_new_filter(&self) -> bool {
534        matches!(self, RouteNetlinkMessage::NewTrafficFilter(_))
535    }
536
537    pub fn is_del_filter(&self) -> bool {
538        matches!(self, RouteNetlinkMessage::DelTrafficFilter(_))
539    }
540
541    pub fn is_get_filter(&self) -> bool {
542        matches!(self, RouteNetlinkMessage::GetTrafficFilter(_))
543    }
544
545    pub fn is_new_chain(&self) -> bool {
546        matches!(self, RouteNetlinkMessage::NewTrafficChain(_))
547    }
548
549    pub fn is_del_chain(&self) -> bool {
550        matches!(self, RouteNetlinkMessage::DelTrafficChain(_))
551    }
552
553    pub fn is_get_chain(&self) -> bool {
554        matches!(self, RouteNetlinkMessage::GetTrafficChain(_))
555    }
556
557    pub fn is_new_nsid(&self) -> bool {
558        matches!(self, RouteNetlinkMessage::NewNsId(_))
559    }
560
561    pub fn is_get_nsid(&self) -> bool {
562        matches!(self, RouteNetlinkMessage::GetNsId(_))
563    }
564
565    pub fn is_del_nsid(&self) -> bool {
566        matches!(self, RouteNetlinkMessage::DelNsId(_))
567    }
568
569    pub fn is_get_rule(&self) -> bool {
570        matches!(self, RouteNetlinkMessage::GetRule(_))
571    }
572
573    pub fn is_new_rule(&self) -> bool {
574        matches!(self, RouteNetlinkMessage::NewRule(_))
575    }
576
577    pub fn is_del_rule(&self) -> bool {
578        matches!(self, RouteNetlinkMessage::DelRule(_))
579    }
580
581    pub fn message_type(&self) -> u16 {
582        use self::RouteNetlinkMessage::*;
583
584        match self {
585            NewLink(_) => RTM_NEWLINK,
586            DelLink(_) => RTM_DELLINK,
587            GetLink(_) => RTM_GETLINK,
588            SetLink(_) => RTM_SETLINK,
589            NewLinkProp(_) => RTM_NEWLINKPROP,
590            DelLinkProp(_) => RTM_DELLINKPROP,
591            NewAddress(_) => RTM_NEWADDR,
592            DelAddress(_) => RTM_DELADDR,
593            GetAddress(_) => RTM_GETADDR,
594            GetNeighbour(_) => RTM_GETNEIGH,
595            NewNeighbour(_) => RTM_NEWNEIGH,
596            DelNeighbour(_) => RTM_DELNEIGH,
597            GetNeighbourTable(_) => RTM_GETNEIGHTBL,
598            NewNeighbourTable(_) => RTM_NEWNEIGHTBL,
599            SetNeighbourTable(_) => RTM_SETNEIGHTBL,
600            NewNeighbourDiscoveryUserOption(_) => RTM_NEWNDUSEROPT,
601            NewRoute(_) => RTM_NEWROUTE,
602            DelRoute(_) => RTM_DELROUTE,
603            GetRoute(_) => RTM_GETROUTE,
604            NewPrefix(_) => RTM_NEWPREFIX,
605            NewQueueDiscipline(_) => RTM_NEWQDISC,
606            DelQueueDiscipline(_) => RTM_DELQDISC,
607            GetQueueDiscipline(_) => RTM_GETQDISC,
608            NewTrafficClass(_) => RTM_NEWTCLASS,
609            DelTrafficClass(_) => RTM_DELTCLASS,
610            GetTrafficClass(_) => RTM_GETTCLASS,
611            NewTrafficFilter(_) => RTM_NEWTFILTER,
612            DelTrafficFilter(_) => RTM_DELTFILTER,
613            GetTrafficFilter(_) => RTM_GETTFILTER,
614            NewTrafficChain(_) => RTM_NEWCHAIN,
615            DelTrafficChain(_) => RTM_DELCHAIN,
616            GetTrafficChain(_) => RTM_GETCHAIN,
617            GetNsId(_) => RTM_GETNSID,
618            NewNsId(_) => RTM_NEWNSID,
619            DelNsId(_) => RTM_DELNSID,
620            GetRule(_) => RTM_GETRULE,
621            NewRule(_) => RTM_NEWRULE,
622            DelRule(_) => RTM_DELRULE,
623        }
624    }
625}
626
627impl Emitable for RouteNetlinkMessage {
628    #[rustfmt::skip]
629    fn buffer_len(&self) -> usize {
630        use self::RouteNetlinkMessage::*;
631        match self {
632            | NewLink(msg)
633            | DelLink(msg)
634            | GetLink(msg)
635            | SetLink(msg)
636            | NewLinkProp(msg)
637            | DelLinkProp(msg)
638            =>  msg.buffer_len(),
639
640            | NewAddress(msg)
641            | DelAddress(msg)
642            | GetAddress(msg)
643            => msg.buffer_len(),
644
645            | NewNeighbour(msg)
646            | GetNeighbour(msg)
647            | DelNeighbour(msg)
648            => msg.buffer_len(),
649
650            | NewNeighbourTable(msg)
651            | GetNeighbourTable(msg)
652            | SetNeighbourTable(msg)
653            => msg.buffer_len(),
654
655            | NewNeighbourDiscoveryUserOption(msg) => msg.buffer_len(),
656
657            | NewRoute(msg)
658            | DelRoute(msg)
659            | GetRoute(msg)
660            => msg.buffer_len(),
661
662            NewPrefix(msg) => msg.buffer_len(),
663
664            | NewQueueDiscipline(msg)
665            | DelQueueDiscipline(msg)
666            | GetQueueDiscipline(msg)
667            | NewTrafficClass(msg)
668            | DelTrafficClass(msg)
669            | GetTrafficClass(msg)
670            | NewTrafficFilter(msg)
671            | DelTrafficFilter(msg)
672            | GetTrafficFilter(msg)
673            | NewTrafficChain(msg)
674            | DelTrafficChain(msg)
675            | GetTrafficChain(msg)
676            => msg.buffer_len(),
677
678            | NewNsId(msg)
679            | DelNsId(msg)
680            | GetNsId(msg)
681            => msg.buffer_len(),
682
683            | NewRule(msg)
684            | DelRule(msg)
685            | GetRule(msg)
686            => msg.buffer_len()
687        }
688    }
689
690    #[rustfmt::skip]
691    fn emit(&self, buffer: &mut [u8]) {
692        use self::RouteNetlinkMessage::*;
693        match self {
694            | NewLink(msg)
695            | DelLink(msg)
696            | GetLink(msg)
697            | SetLink(msg)
698            | NewLinkProp(msg)
699            | DelLinkProp(msg)
700            => msg.emit(buffer),
701
702            | NewAddress(msg)
703            | DelAddress(msg)
704            | GetAddress(msg)
705            => msg.emit(buffer),
706
707            | GetNeighbour(msg)
708            | NewNeighbour(msg)
709            | DelNeighbour(msg)
710            => msg.emit(buffer),
711
712            | GetNeighbourTable(msg)
713            | NewNeighbourTable(msg)
714            | SetNeighbourTable(msg)
715            => msg.emit(buffer),
716
717            | NewNeighbourDiscoveryUserOption(msg) => msg.emit(buffer),
718
719            | NewRoute(msg)
720            | DelRoute(msg)
721            | GetRoute(msg)
722            => msg.emit(buffer),
723
724            | NewPrefix(msg) => msg.emit(buffer),
725
726            | NewQueueDiscipline(msg)
727            | DelQueueDiscipline(msg)
728            | GetQueueDiscipline(msg)
729            | NewTrafficClass(msg)
730            | DelTrafficClass(msg)
731            | GetTrafficClass(msg)
732            | NewTrafficFilter(msg)
733            | DelTrafficFilter(msg)
734            | GetTrafficFilter(msg)
735            | NewTrafficChain(msg)
736            | DelTrafficChain(msg)
737            | GetTrafficChain(msg)
738            => msg.emit(buffer),
739
740            | NewNsId(msg)
741            | DelNsId(msg)
742            | GetNsId(msg)
743            => msg.emit(buffer),
744
745            | NewRule(msg)
746            | DelRule(msg)
747            | GetRule(msg)
748            => msg.emit(buffer)
749        }
750    }
751}
752
753impl NetlinkSerializable for RouteNetlinkMessage {
754    fn message_type(&self) -> u16 {
755        self.message_type()
756    }
757
758    fn buffer_len(&self) -> usize {
759        <Self as Emitable>::buffer_len(self)
760    }
761
762    fn serialize(&self, buffer: &mut [u8]) {
763        self.emit(buffer)
764    }
765}
766
767impl NetlinkDeserializable for RouteNetlinkMessage {
768    type Error = RouteNetlinkMessageParseError;
769
770    fn deserialize(header: &NetlinkHeader, payload: &[u8]) -> Result<Self, Self::Error> {
771        let buf = RouteNetlinkMessageBuffer::new(payload);
772        match RouteNetlinkMessage::parse_with_param(&buf, header.message_type) {
773            Err(e) => Err(e),
774            Ok(message) => Ok(message),
775        }
776    }
777}
778
779impl From<RouteNetlinkMessage> for NetlinkPayload<RouteNetlinkMessage> {
780    fn from(message: RouteNetlinkMessage) -> Self {
781        NetlinkPayload::InnerMessage(message)
782    }
783}