Skip to main content

netlink_packet_route/
message.rs

1// SPDX-License-Identifier: MIT
2
3use crate::address::{AddressError, AddressHeader, AddressMessage, AddressMessageBuffer};
4use crate::link::{LinkMessage, LinkMessageBuffer};
5use crate::neighbour::{NeighbourError, NeighbourMessage, NeighbourMessageBuffer};
6use crate::neighbour_discovery_user_option::{
7    NeighbourDiscoveryUserOptionError, NeighbourDiscoveryUserOptionMessage,
8    NeighbourDiscoveryUserOptionMessageBuffer,
9};
10use crate::neighbour_table::{
11    NeighbourTableError, NeighbourTableMessage, NeighbourTableMessageBuffer,
12};
13use crate::nsid::{NsidError, NsidMessage, NsidMessageBuffer};
14use crate::prefix::{PrefixError, PrefixMessage, PrefixMessageBuffer};
15use crate::route::{RouteError, RouteHeader, RouteMessage, RouteMessageBuffer};
16use crate::rule::{RuleError, RuleMessage, RuleMessageBuffer};
17use crate::tc::{TcError, TcMessage, TcMessageBuffer};
18use netlink_packet_core::{
19    NetlinkDeserializable, NetlinkHeader, NetlinkPayload, NetlinkSerializable,
20};
21use netlink_packet_utils::nla::NlaParseMode;
22use netlink_packet_utils::{DecodeError, Emitable, 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/// Describes how to handle errors when parsing `NETLINK_ROUTE` messages.
131#[derive(Default)]
132pub enum RouteNetlinkMessageParseMode {
133    /// Parsing fails if fields are not correctly initialized. Corresponds to
134    /// the `NETLINK_GET_STRICT_CHK` option.
135    #[default]
136    Strict,
137    /// Parsing may not fail if e.g. irrelevant fields are set or
138    /// unknown/invalid attributes are provided.
139    Relaxed,
140}
141
142impl From<RouteNetlinkMessageParseMode> for NlaParseMode {
143    fn from(mode: RouteNetlinkMessageParseMode) -> Self {
144        match mode {
145            RouteNetlinkMessageParseMode::Strict => NlaParseMode::Strict,
146            RouteNetlinkMessageParseMode::Relaxed => NlaParseMode::Relaxed,
147        }
148    }
149}
150
151struct RouteNetlinkMessageParseConfig {
152    message_type: u16,
153    parse_mode: RouteNetlinkMessageParseMode,
154}
155
156impl<'a, T: AsRef<[u8]> + ?Sized>
157    ParseableParametrized<RouteNetlinkMessageBuffer<&'a T>, RouteNetlinkMessageParseConfig>
158    for RouteNetlinkMessage
159{
160    type Error = RouteNetlinkMessageParseError;
161
162    fn parse_with_param(
163        buf: &RouteNetlinkMessageBuffer<&'a T>,
164        RouteNetlinkMessageParseConfig { message_type, parse_mode }: RouteNetlinkMessageParseConfig,
165    ) -> Result<Self, Self::Error> {
166        let message = match message_type {
167            // Link messages
168            RTM_NEWLINK | RTM_GETLINK | RTM_DELLINK | RTM_SETLINK => {
169                let msg = match LinkMessageBuffer::new(&buf.inner()) {
170                    Ok(buf) => LinkMessage::parse_with_param(&buf, parse_mode)
171                        .map_err(RouteNetlinkMessageParseError::InvalidLinkMessage)?,
172                    // HACK: iproute2 sends invalid RTM_GETLINK message, where
173                    // the header is limited to the
174                    // interface family (1 byte) and 3 bytes of padding.
175                    Err(e) => {
176                        if buf.inner().len() == 4 && message_type == RTM_GETLINK {
177                            let mut msg = LinkMessage::default();
178                            msg.header.interface_family = buf.inner()[0].into();
179                            msg
180                        } else {
181                            return Err(RouteNetlinkMessageParseError::InvalidLinkMessage(e));
182                        }
183                    }
184                };
185                match message_type {
186                    RTM_NEWLINK => RouteNetlinkMessage::NewLink(msg),
187                    RTM_GETLINK => RouteNetlinkMessage::GetLink(msg),
188                    RTM_DELLINK => RouteNetlinkMessage::DelLink(msg),
189                    RTM_SETLINK => RouteNetlinkMessage::SetLink(msg),
190                    _ => unreachable!(),
191                }
192            }
193
194            // Address messages
195            RTM_NEWADDR | RTM_GETADDR | RTM_DELADDR => {
196                let msg = match AddressMessageBuffer::new(&buf.inner()) {
197                    Ok(buffer) => AddressMessage::parse_with_param(&buffer, parse_mode)?,
198                    // HACK: iproute2 sends invalid RTM_GETADDR message, where
199                    // the header is limited to the
200                    // interface family (1 byte) and 3 bytes of padding.
201                    Err(e) => {
202                        if buf.inner().len() == 4 && message_type == RTM_GETADDR {
203                            let mut msg = AddressMessage {
204                                header: AddressHeader::default(),
205                                attributes: vec![],
206                            };
207                            msg.header.family = buf.inner()[0].into();
208                            msg
209                        } else {
210                            return Err(RouteNetlinkMessageParseError::InvalidAddrMessage(
211                                AddressError::FailedBufferInit(e),
212                            ));
213                        }
214                    }
215                };
216                match message_type {
217                    RTM_NEWADDR => RouteNetlinkMessage::NewAddress(msg),
218                    RTM_GETADDR => RouteNetlinkMessage::GetAddress(msg),
219                    RTM_DELADDR => RouteNetlinkMessage::DelAddress(msg),
220                    _ => unreachable!(),
221                }
222            }
223
224            // Neighbour messages
225            RTM_NEWNEIGH | RTM_GETNEIGH | RTM_DELNEIGH => {
226                let buf_inner = buf.inner();
227                let buffer = NeighbourMessageBuffer::new(&buf_inner)
228                    .map_err(RouteNetlinkMessageParseError::ParseBuffer)?;
229                let msg = NeighbourMessage::parse_with_param(&buffer, parse_mode)?;
230                match message_type {
231                    RTM_GETNEIGH => RouteNetlinkMessage::GetNeighbour(msg),
232                    RTM_NEWNEIGH => RouteNetlinkMessage::NewNeighbour(msg),
233                    RTM_DELNEIGH => RouteNetlinkMessage::DelNeighbour(msg),
234                    _ => unreachable!(),
235                }
236            }
237
238            // Neighbour table messages
239            RTM_NEWNEIGHTBL | RTM_GETNEIGHTBL | RTM_SETNEIGHTBL => {
240                let buf_inner = buf.inner();
241                let buffer = NeighbourTableMessageBuffer::new(&buf_inner)
242                    .map_err(RouteNetlinkMessageParseError::ParseBuffer)?;
243                let msg = NeighbourTableMessage::parse_with_param(&buffer, parse_mode)
244                    .map_err(RouteNetlinkMessageParseError::InvalidNeighbourTableMessage)?;
245                match message_type {
246                    RTM_GETNEIGHTBL => RouteNetlinkMessage::GetNeighbourTable(msg),
247                    RTM_NEWNEIGHTBL => RouteNetlinkMessage::NewNeighbourTable(msg),
248                    RTM_SETNEIGHTBL => RouteNetlinkMessage::SetNeighbourTable(msg),
249                    _ => unreachable!(),
250                }
251            }
252
253            RTM_NEWNDUSEROPT => {
254                let msg = NeighbourDiscoveryUserOptionMessage::parse_with_param(
255                    &NeighbourDiscoveryUserOptionMessageBuffer::new(&buf.inner())
256                        .map_err(NeighbourDiscoveryUserOptionError::ParseBuffer)?,
257                    parse_mode,
258                )?;
259                RouteNetlinkMessage::NewNeighbourDiscoveryUserOption(msg)
260            }
261
262            // Route messages
263            RTM_NEWROUTE | RTM_GETROUTE | RTM_DELROUTE => {
264                let msg = match RouteMessageBuffer::new(&buf.inner()) {
265                    Ok(buffer) => RouteMessage::parse_with_param(&buffer, parse_mode)?,
266                    // HACK: iproute2 sends invalid RTM_GETROUTE message, where
267                    // the header is limited to the
268                    // interface family (1 byte) and 3 bytes of padding.
269                    Err(e) => {
270                        // Not only does iproute2 sends invalid messages, it's
271                        // also inconsistent in
272                        // doing so: for link and address messages, the length
273                        // advertised in the
274                        // netlink header includes the 3 bytes of padding but it
275                        // does not seem to be the case
276                        // for the route message, hence the buf.length() == 1
277                        // check.
278                        if (buf.inner().len() == 4 || buf.inner().len() == 1)
279                            && message_type == RTM_GETROUTE
280                        {
281                            let mut msg =
282                                RouteMessage { header: RouteHeader::default(), attributes: vec![] };
283                            msg.header.address_family = buf.inner()[0].into();
284                            msg
285                        } else {
286                            return Err(RouteNetlinkMessageParseError::ParseBuffer(e));
287                        }
288                    }
289                };
290                match message_type {
291                    RTM_NEWROUTE => RouteNetlinkMessage::NewRoute(msg),
292                    RTM_GETROUTE => RouteNetlinkMessage::GetRoute(msg),
293                    RTM_DELROUTE => RouteNetlinkMessage::DelRoute(msg),
294                    _ => unreachable!(),
295                }
296            }
297
298            // Prefix messages
299            RTM_NEWPREFIX => {
300                let buf_inner = buf.inner();
301                let buffer = PrefixMessageBuffer::new(&buf_inner)
302                    .map_err(RouteNetlinkMessageParseError::ParseBuffer)?;
303                RouteNetlinkMessage::NewPrefix(PrefixMessage::parse_with_param(
304                    &buffer, parse_mode,
305                )?)
306            }
307            RTM_NEWRULE | RTM_GETRULE | RTM_DELRULE => {
308                let buf_inner = buf.inner();
309                let buffer = RuleMessageBuffer::new(&buf_inner)
310                    .map_err(RouteNetlinkMessageParseError::ParseBuffer)?;
311                let msg = RuleMessage::parse_with_param(&buffer, parse_mode)?;
312                match message_type {
313                    RTM_NEWRULE => RouteNetlinkMessage::NewRule(msg),
314                    RTM_DELRULE => RouteNetlinkMessage::DelRule(msg),
315                    RTM_GETRULE => RouteNetlinkMessage::GetRule(msg),
316                    _ => unreachable!(),
317                }
318            }
319            // TC Messages
320            RTM_NEWQDISC | RTM_DELQDISC | RTM_GETQDISC | RTM_NEWTCLASS | RTM_DELTCLASS
321            | RTM_GETTCLASS | RTM_NEWTFILTER | RTM_DELTFILTER | RTM_GETTFILTER | RTM_NEWCHAIN
322            | RTM_DELCHAIN | RTM_GETCHAIN => {
323                let buf_inner = buf.inner();
324                let buffer = TcMessageBuffer::new(&buf_inner)
325                    .map_err(RouteNetlinkMessageParseError::ParseBuffer)?;
326                let msg = TcMessage::parse_with_param(&buffer, parse_mode)?;
327                match message_type {
328                    RTM_NEWQDISC => RouteNetlinkMessage::NewQueueDiscipline(msg),
329                    RTM_DELQDISC => RouteNetlinkMessage::DelQueueDiscipline(msg),
330                    RTM_GETQDISC => RouteNetlinkMessage::GetQueueDiscipline(msg),
331                    RTM_NEWTCLASS => RouteNetlinkMessage::NewTrafficClass(msg),
332                    RTM_DELTCLASS => RouteNetlinkMessage::DelTrafficClass(msg),
333                    RTM_GETTCLASS => RouteNetlinkMessage::GetTrafficClass(msg),
334                    RTM_NEWTFILTER => RouteNetlinkMessage::NewTrafficFilter(msg),
335                    RTM_DELTFILTER => RouteNetlinkMessage::DelTrafficFilter(msg),
336                    RTM_GETTFILTER => RouteNetlinkMessage::GetTrafficFilter(msg),
337                    RTM_NEWCHAIN => RouteNetlinkMessage::NewTrafficChain(msg),
338                    RTM_DELCHAIN => RouteNetlinkMessage::DelTrafficChain(msg),
339                    RTM_GETCHAIN => RouteNetlinkMessage::GetTrafficChain(msg),
340                    _ => unreachable!(),
341                }
342            }
343
344            // ND ID Messages
345            RTM_NEWNSID | RTM_GETNSID | RTM_DELNSID => {
346                let buf_inner = buf.inner();
347                let buffer = NsidMessageBuffer::new(&buf_inner)
348                    .map_err(RouteNetlinkMessageParseError::ParseBuffer)?;
349                let msg = NsidMessage::parse_with_param(&buffer, parse_mode)?;
350                match message_type {
351                    RTM_NEWNSID => RouteNetlinkMessage::NewNsId(msg),
352                    RTM_DELNSID => RouteNetlinkMessage::DelNsId(msg),
353                    RTM_GETNSID => RouteNetlinkMessage::GetNsId(msg),
354                    _ => unreachable!(),
355                }
356            }
357
358            _ => return Err(RouteNetlinkMessageParseError::UnknownMessageType(message_type)),
359        };
360        Ok(message)
361    }
362}
363
364#[derive(Debug, PartialEq, Eq, Clone)]
365pub enum RouteNetlinkMessage {
366    NewLink(LinkMessage),
367    DelLink(LinkMessage),
368    GetLink(LinkMessage),
369    SetLink(LinkMessage),
370    NewLinkProp(LinkMessage),
371    DelLinkProp(LinkMessage),
372    NewAddress(AddressMessage),
373    DelAddress(AddressMessage),
374    GetAddress(AddressMessage),
375    NewNeighbour(NeighbourMessage),
376    GetNeighbour(NeighbourMessage),
377    DelNeighbour(NeighbourMessage),
378    NewNeighbourTable(NeighbourTableMessage),
379    GetNeighbourTable(NeighbourTableMessage),
380    SetNeighbourTable(NeighbourTableMessage),
381    NewNeighbourDiscoveryUserOption(NeighbourDiscoveryUserOptionMessage),
382    NewRoute(RouteMessage),
383    DelRoute(RouteMessage),
384    GetRoute(RouteMessage),
385    NewPrefix(PrefixMessage),
386    NewQueueDiscipline(TcMessage),
387    DelQueueDiscipline(TcMessage),
388    GetQueueDiscipline(TcMessage),
389    NewTrafficClass(TcMessage),
390    DelTrafficClass(TcMessage),
391    GetTrafficClass(TcMessage),
392    NewTrafficFilter(TcMessage),
393    DelTrafficFilter(TcMessage),
394    GetTrafficFilter(TcMessage),
395    NewTrafficChain(TcMessage),
396    DelTrafficChain(TcMessage),
397    GetTrafficChain(TcMessage),
398    NewNsId(NsidMessage),
399    DelNsId(NsidMessage),
400    GetNsId(NsidMessage),
401    NewRule(RuleMessage),
402    DelRule(RuleMessage),
403    GetRule(RuleMessage),
404}
405
406impl RouteNetlinkMessage {
407    pub fn is_new_link(&self) -> bool {
408        matches!(self, RouteNetlinkMessage::NewLink(_))
409    }
410
411    pub fn is_del_link(&self) -> bool {
412        matches!(self, RouteNetlinkMessage::DelLink(_))
413    }
414
415    pub fn is_get_link(&self) -> bool {
416        matches!(self, RouteNetlinkMessage::GetLink(_))
417    }
418
419    pub fn is_set_link(&self) -> bool {
420        matches!(self, RouteNetlinkMessage::SetLink(_))
421    }
422
423    pub fn is_new_address(&self) -> bool {
424        matches!(self, RouteNetlinkMessage::NewAddress(_))
425    }
426
427    pub fn is_del_address(&self) -> bool {
428        matches!(self, RouteNetlinkMessage::DelAddress(_))
429    }
430
431    pub fn is_get_address(&self) -> bool {
432        matches!(self, RouteNetlinkMessage::GetAddress(_))
433    }
434
435    pub fn is_get_neighbour(&self) -> bool {
436        matches!(self, RouteNetlinkMessage::GetNeighbour(_))
437    }
438
439    pub fn is_new_route(&self) -> bool {
440        matches!(self, RouteNetlinkMessage::NewRoute(_))
441    }
442
443    pub fn is_new_neighbour(&self) -> bool {
444        matches!(self, RouteNetlinkMessage::NewNeighbour(_))
445    }
446
447    pub fn is_get_route(&self) -> bool {
448        matches!(self, RouteNetlinkMessage::GetRoute(_))
449    }
450
451    pub fn is_del_neighbour(&self) -> bool {
452        matches!(self, RouteNetlinkMessage::DelNeighbour(_))
453    }
454
455    pub fn is_new_neighbour_table(&self) -> bool {
456        matches!(self, RouteNetlinkMessage::NewNeighbourTable(_))
457    }
458
459    pub fn is_get_neighbour_table(&self) -> bool {
460        matches!(self, RouteNetlinkMessage::GetNeighbourTable(_))
461    }
462
463    pub fn is_set_neighbour_table(&self) -> bool {
464        matches!(self, RouteNetlinkMessage::SetNeighbourTable(_))
465    }
466
467    pub fn is_del_route(&self) -> bool {
468        matches!(self, RouteNetlinkMessage::DelRoute(_))
469    }
470
471    pub fn is_new_qdisc(&self) -> bool {
472        matches!(self, RouteNetlinkMessage::NewQueueDiscipline(_))
473    }
474
475    pub fn is_del_qdisc(&self) -> bool {
476        matches!(self, RouteNetlinkMessage::DelQueueDiscipline(_))
477    }
478
479    pub fn is_get_qdisc(&self) -> bool {
480        matches!(self, RouteNetlinkMessage::GetQueueDiscipline(_))
481    }
482
483    pub fn is_new_class(&self) -> bool {
484        matches!(self, RouteNetlinkMessage::NewTrafficClass(_))
485    }
486
487    pub fn is_del_class(&self) -> bool {
488        matches!(self, RouteNetlinkMessage::DelTrafficClass(_))
489    }
490
491    pub fn is_get_class(&self) -> bool {
492        matches!(self, RouteNetlinkMessage::GetTrafficClass(_))
493    }
494
495    pub fn is_new_filter(&self) -> bool {
496        matches!(self, RouteNetlinkMessage::NewTrafficFilter(_))
497    }
498
499    pub fn is_del_filter(&self) -> bool {
500        matches!(self, RouteNetlinkMessage::DelTrafficFilter(_))
501    }
502
503    pub fn is_get_filter(&self) -> bool {
504        matches!(self, RouteNetlinkMessage::GetTrafficFilter(_))
505    }
506
507    pub fn is_new_chain(&self) -> bool {
508        matches!(self, RouteNetlinkMessage::NewTrafficChain(_))
509    }
510
511    pub fn is_del_chain(&self) -> bool {
512        matches!(self, RouteNetlinkMessage::DelTrafficChain(_))
513    }
514
515    pub fn is_get_chain(&self) -> bool {
516        matches!(self, RouteNetlinkMessage::GetTrafficChain(_))
517    }
518
519    pub fn is_new_nsid(&self) -> bool {
520        matches!(self, RouteNetlinkMessage::NewNsId(_))
521    }
522
523    pub fn is_get_nsid(&self) -> bool {
524        matches!(self, RouteNetlinkMessage::GetNsId(_))
525    }
526
527    pub fn is_del_nsid(&self) -> bool {
528        matches!(self, RouteNetlinkMessage::DelNsId(_))
529    }
530
531    pub fn is_get_rule(&self) -> bool {
532        matches!(self, RouteNetlinkMessage::GetRule(_))
533    }
534
535    pub fn is_new_rule(&self) -> bool {
536        matches!(self, RouteNetlinkMessage::NewRule(_))
537    }
538
539    pub fn is_del_rule(&self) -> bool {
540        matches!(self, RouteNetlinkMessage::DelRule(_))
541    }
542
543    pub fn message_type(&self) -> u16 {
544        use self::RouteNetlinkMessage::*;
545
546        match self {
547            NewLink(_) => RTM_NEWLINK,
548            DelLink(_) => RTM_DELLINK,
549            GetLink(_) => RTM_GETLINK,
550            SetLink(_) => RTM_SETLINK,
551            NewLinkProp(_) => RTM_NEWLINKPROP,
552            DelLinkProp(_) => RTM_DELLINKPROP,
553            NewAddress(_) => RTM_NEWADDR,
554            DelAddress(_) => RTM_DELADDR,
555            GetAddress(_) => RTM_GETADDR,
556            GetNeighbour(_) => RTM_GETNEIGH,
557            NewNeighbour(_) => RTM_NEWNEIGH,
558            DelNeighbour(_) => RTM_DELNEIGH,
559            GetNeighbourTable(_) => RTM_GETNEIGHTBL,
560            NewNeighbourTable(_) => RTM_NEWNEIGHTBL,
561            SetNeighbourTable(_) => RTM_SETNEIGHTBL,
562            NewNeighbourDiscoveryUserOption(_) => RTM_NEWNDUSEROPT,
563            NewRoute(_) => RTM_NEWROUTE,
564            DelRoute(_) => RTM_DELROUTE,
565            GetRoute(_) => RTM_GETROUTE,
566            NewPrefix(_) => RTM_NEWPREFIX,
567            NewQueueDiscipline(_) => RTM_NEWQDISC,
568            DelQueueDiscipline(_) => RTM_DELQDISC,
569            GetQueueDiscipline(_) => RTM_GETQDISC,
570            NewTrafficClass(_) => RTM_NEWTCLASS,
571            DelTrafficClass(_) => RTM_DELTCLASS,
572            GetTrafficClass(_) => RTM_GETTCLASS,
573            NewTrafficFilter(_) => RTM_NEWTFILTER,
574            DelTrafficFilter(_) => RTM_DELTFILTER,
575            GetTrafficFilter(_) => RTM_GETTFILTER,
576            NewTrafficChain(_) => RTM_NEWCHAIN,
577            DelTrafficChain(_) => RTM_DELCHAIN,
578            GetTrafficChain(_) => RTM_GETCHAIN,
579            GetNsId(_) => RTM_GETNSID,
580            NewNsId(_) => RTM_NEWNSID,
581            DelNsId(_) => RTM_DELNSID,
582            GetRule(_) => RTM_GETRULE,
583            NewRule(_) => RTM_NEWRULE,
584            DelRule(_) => RTM_DELRULE,
585        }
586    }
587}
588
589impl Emitable for RouteNetlinkMessage {
590    #[rustfmt::skip]
591    fn buffer_len(&self) -> usize {
592        use self::RouteNetlinkMessage::*;
593        match self {
594            | NewLink(msg)
595            | DelLink(msg)
596            | GetLink(msg)
597            | SetLink(msg)
598            | NewLinkProp(msg)
599            | DelLinkProp(msg)
600            =>  msg.buffer_len(),
601
602            | NewAddress(msg)
603            | DelAddress(msg)
604            | GetAddress(msg)
605            => msg.buffer_len(),
606
607            | NewNeighbour(msg)
608            | GetNeighbour(msg)
609            | DelNeighbour(msg)
610            => msg.buffer_len(),
611
612            | NewNeighbourTable(msg)
613            | GetNeighbourTable(msg)
614            | SetNeighbourTable(msg)
615            => msg.buffer_len(),
616
617            | NewNeighbourDiscoveryUserOption(msg) => msg.buffer_len(),
618
619            | NewRoute(msg)
620            | DelRoute(msg)
621            | GetRoute(msg)
622            => msg.buffer_len(),
623
624            NewPrefix(msg) => msg.buffer_len(),
625
626            | NewQueueDiscipline(msg)
627            | DelQueueDiscipline(msg)
628            | GetQueueDiscipline(msg)
629            | NewTrafficClass(msg)
630            | DelTrafficClass(msg)
631            | GetTrafficClass(msg)
632            | NewTrafficFilter(msg)
633            | DelTrafficFilter(msg)
634            | GetTrafficFilter(msg)
635            | NewTrafficChain(msg)
636            | DelTrafficChain(msg)
637            | GetTrafficChain(msg)
638            => msg.buffer_len(),
639
640            | NewNsId(msg)
641            | DelNsId(msg)
642            | GetNsId(msg)
643            => msg.buffer_len(),
644
645            | NewRule(msg)
646            | DelRule(msg)
647            | GetRule(msg)
648            => msg.buffer_len()
649        }
650    }
651
652    #[rustfmt::skip]
653    fn emit(&self, buffer: &mut [u8]) {
654        use self::RouteNetlinkMessage::*;
655        match self {
656            | NewLink(msg)
657            | DelLink(msg)
658            | GetLink(msg)
659            | SetLink(msg)
660            | NewLinkProp(msg)
661            | DelLinkProp(msg)
662            => msg.emit(buffer),
663
664            | NewAddress(msg)
665            | DelAddress(msg)
666            | GetAddress(msg)
667            => msg.emit(buffer),
668
669            | GetNeighbour(msg)
670            | NewNeighbour(msg)
671            | DelNeighbour(msg)
672            => msg.emit(buffer),
673
674            | GetNeighbourTable(msg)
675            | NewNeighbourTable(msg)
676            | SetNeighbourTable(msg)
677            => msg.emit(buffer),
678
679            | NewNeighbourDiscoveryUserOption(msg) => msg.emit(buffer),
680
681            | NewRoute(msg)
682            | DelRoute(msg)
683            | GetRoute(msg)
684            => msg.emit(buffer),
685
686            | NewPrefix(msg) => msg.emit(buffer),
687
688            | NewQueueDiscipline(msg)
689            | DelQueueDiscipline(msg)
690            | GetQueueDiscipline(msg)
691            | NewTrafficClass(msg)
692            | DelTrafficClass(msg)
693            | GetTrafficClass(msg)
694            | NewTrafficFilter(msg)
695            | DelTrafficFilter(msg)
696            | GetTrafficFilter(msg)
697            | NewTrafficChain(msg)
698            | DelTrafficChain(msg)
699            | GetTrafficChain(msg)
700            => msg.emit(buffer),
701
702            | NewNsId(msg)
703            | DelNsId(msg)
704            | GetNsId(msg)
705            => msg.emit(buffer),
706
707            | NewRule(msg)
708            | DelRule(msg)
709            | GetRule(msg)
710            => msg.emit(buffer)
711        }
712    }
713}
714
715impl NetlinkSerializable for RouteNetlinkMessage {
716    fn message_type(&self) -> u16 {
717        self.message_type()
718    }
719
720    fn buffer_len(&self) -> usize {
721        <Self as Emitable>::buffer_len(self)
722    }
723
724    fn serialize(&self, buffer: &mut [u8]) {
725        self.emit(buffer)
726    }
727}
728
729impl NetlinkDeserializable for RouteNetlinkMessage {
730    type DeserializeOptions = RouteNetlinkMessageParseMode;
731    type Error = RouteNetlinkMessageParseError;
732
733    fn deserialize(
734        header: &NetlinkHeader,
735        payload: &[u8],
736        options: RouteNetlinkMessageParseMode,
737    ) -> Result<Self, Self::Error> {
738        let buf = RouteNetlinkMessageBuffer::new(payload);
739        match RouteNetlinkMessage::parse_with_param(
740            &buf,
741            RouteNetlinkMessageParseConfig {
742                message_type: header.message_type,
743                parse_mode: options,
744            },
745        ) {
746            Err(e) => Err(e),
747            Ok(message) => Ok(message),
748        }
749    }
750}
751
752impl From<RouteNetlinkMessage> for NetlinkPayload<RouteNetlinkMessage> {
753    fn from(message: RouteNetlinkMessage) -> Self {
754        NetlinkPayload::InnerMessage(message)
755    }
756}