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