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_checked(&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_checked(&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_checked(&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_checked(&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_checked(&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_checked(&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_checked(&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_checked(&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_checked(&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_checked(&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)]
334#[non_exhaustive]
335pub enum RouteNetlinkMessage {
336    NewLink(LinkMessage),
337    DelLink(LinkMessage),
338    GetLink(LinkMessage),
339    SetLink(LinkMessage),
340    NewLinkProp(LinkMessage),
341    DelLinkProp(LinkMessage),
342    NewAddress(AddressMessage),
343    DelAddress(AddressMessage),
344    GetAddress(AddressMessage),
345    NewNeighbour(NeighbourMessage),
346    GetNeighbour(NeighbourMessage),
347    DelNeighbour(NeighbourMessage),
348    NewNeighbourTable(NeighbourTableMessage),
349    GetNeighbourTable(NeighbourTableMessage),
350    SetNeighbourTable(NeighbourTableMessage),
351    NewNeighbourDiscoveryUserOption(NeighbourDiscoveryUserOptionMessage),
352    NewRoute(RouteMessage),
353    DelRoute(RouteMessage),
354    GetRoute(RouteMessage),
355    NewPrefix(PrefixMessage),
356    NewQueueDiscipline(TcMessage),
357    DelQueueDiscipline(TcMessage),
358    GetQueueDiscipline(TcMessage),
359    NewTrafficClass(TcMessage),
360    DelTrafficClass(TcMessage),
361    GetTrafficClass(TcMessage),
362    NewTrafficFilter(TcMessage),
363    DelTrafficFilter(TcMessage),
364    GetTrafficFilter(TcMessage),
365    NewTrafficChain(TcMessage),
366    DelTrafficChain(TcMessage),
367    GetTrafficChain(TcMessage),
368    NewNsId(NsidMessage),
369    DelNsId(NsidMessage),
370    GetNsId(NsidMessage),
371    NewRule(RuleMessage),
372    DelRule(RuleMessage),
373    GetRule(RuleMessage),
374}
375
376impl RouteNetlinkMessage {
377    pub fn is_new_link(&self) -> bool {
378        matches!(self, RouteNetlinkMessage::NewLink(_))
379    }
380
381    pub fn is_del_link(&self) -> bool {
382        matches!(self, RouteNetlinkMessage::DelLink(_))
383    }
384
385    pub fn is_get_link(&self) -> bool {
386        matches!(self, RouteNetlinkMessage::GetLink(_))
387    }
388
389    pub fn is_set_link(&self) -> bool {
390        matches!(self, RouteNetlinkMessage::SetLink(_))
391    }
392
393    pub fn is_new_address(&self) -> bool {
394        matches!(self, RouteNetlinkMessage::NewAddress(_))
395    }
396
397    pub fn is_del_address(&self) -> bool {
398        matches!(self, RouteNetlinkMessage::DelAddress(_))
399    }
400
401    pub fn is_get_address(&self) -> bool {
402        matches!(self, RouteNetlinkMessage::GetAddress(_))
403    }
404
405    pub fn is_get_neighbour(&self) -> bool {
406        matches!(self, RouteNetlinkMessage::GetNeighbour(_))
407    }
408
409    pub fn is_new_route(&self) -> bool {
410        matches!(self, RouteNetlinkMessage::NewRoute(_))
411    }
412
413    pub fn is_new_neighbour(&self) -> bool {
414        matches!(self, RouteNetlinkMessage::NewNeighbour(_))
415    }
416
417    pub fn is_get_route(&self) -> bool {
418        matches!(self, RouteNetlinkMessage::GetRoute(_))
419    }
420
421    pub fn is_del_neighbour(&self) -> bool {
422        matches!(self, RouteNetlinkMessage::DelNeighbour(_))
423    }
424
425    pub fn is_new_neighbour_table(&self) -> bool {
426        matches!(self, RouteNetlinkMessage::NewNeighbourTable(_))
427    }
428
429    pub fn is_get_neighbour_table(&self) -> bool {
430        matches!(self, RouteNetlinkMessage::GetNeighbourTable(_))
431    }
432
433    pub fn is_set_neighbour_table(&self) -> bool {
434        matches!(self, RouteNetlinkMessage::SetNeighbourTable(_))
435    }
436
437    pub fn is_del_route(&self) -> bool {
438        matches!(self, RouteNetlinkMessage::DelRoute(_))
439    }
440
441    pub fn is_new_qdisc(&self) -> bool {
442        matches!(self, RouteNetlinkMessage::NewQueueDiscipline(_))
443    }
444
445    pub fn is_del_qdisc(&self) -> bool {
446        matches!(self, RouteNetlinkMessage::DelQueueDiscipline(_))
447    }
448
449    pub fn is_get_qdisc(&self) -> bool {
450        matches!(self, RouteNetlinkMessage::GetQueueDiscipline(_))
451    }
452
453    pub fn is_new_class(&self) -> bool {
454        matches!(self, RouteNetlinkMessage::NewTrafficClass(_))
455    }
456
457    pub fn is_del_class(&self) -> bool {
458        matches!(self, RouteNetlinkMessage::DelTrafficClass(_))
459    }
460
461    pub fn is_get_class(&self) -> bool {
462        matches!(self, RouteNetlinkMessage::GetTrafficClass(_))
463    }
464
465    pub fn is_new_filter(&self) -> bool {
466        matches!(self, RouteNetlinkMessage::NewTrafficFilter(_))
467    }
468
469    pub fn is_del_filter(&self) -> bool {
470        matches!(self, RouteNetlinkMessage::DelTrafficFilter(_))
471    }
472
473    pub fn is_get_filter(&self) -> bool {
474        matches!(self, RouteNetlinkMessage::GetTrafficFilter(_))
475    }
476
477    pub fn is_new_chain(&self) -> bool {
478        matches!(self, RouteNetlinkMessage::NewTrafficChain(_))
479    }
480
481    pub fn is_del_chain(&self) -> bool {
482        matches!(self, RouteNetlinkMessage::DelTrafficChain(_))
483    }
484
485    pub fn is_get_chain(&self) -> bool {
486        matches!(self, RouteNetlinkMessage::GetTrafficChain(_))
487    }
488
489    pub fn is_new_nsid(&self) -> bool {
490        matches!(self, RouteNetlinkMessage::NewNsId(_))
491    }
492
493    pub fn is_get_nsid(&self) -> bool {
494        matches!(self, RouteNetlinkMessage::GetNsId(_))
495    }
496
497    pub fn is_del_nsid(&self) -> bool {
498        matches!(self, RouteNetlinkMessage::DelNsId(_))
499    }
500
501    pub fn is_get_rule(&self) -> bool {
502        matches!(self, RouteNetlinkMessage::GetRule(_))
503    }
504
505    pub fn is_new_rule(&self) -> bool {
506        matches!(self, RouteNetlinkMessage::NewRule(_))
507    }
508
509    pub fn is_del_rule(&self) -> bool {
510        matches!(self, RouteNetlinkMessage::DelRule(_))
511    }
512
513    pub fn message_type(&self) -> u16 {
514        use self::RouteNetlinkMessage::*;
515
516        match self {
517            NewLink(_) => RTM_NEWLINK,
518            DelLink(_) => RTM_DELLINK,
519            GetLink(_) => RTM_GETLINK,
520            SetLink(_) => RTM_SETLINK,
521            NewLinkProp(_) => RTM_NEWLINKPROP,
522            DelLinkProp(_) => RTM_DELLINKPROP,
523            NewAddress(_) => RTM_NEWADDR,
524            DelAddress(_) => RTM_DELADDR,
525            GetAddress(_) => RTM_GETADDR,
526            GetNeighbour(_) => RTM_GETNEIGH,
527            NewNeighbour(_) => RTM_NEWNEIGH,
528            DelNeighbour(_) => RTM_DELNEIGH,
529            GetNeighbourTable(_) => RTM_GETNEIGHTBL,
530            NewNeighbourTable(_) => RTM_NEWNEIGHTBL,
531            SetNeighbourTable(_) => RTM_SETNEIGHTBL,
532            NewNeighbourDiscoveryUserOption(_) => RTM_NEWNDUSEROPT,
533            NewRoute(_) => RTM_NEWROUTE,
534            DelRoute(_) => RTM_DELROUTE,
535            GetRoute(_) => RTM_GETROUTE,
536            NewPrefix(_) => RTM_NEWPREFIX,
537            NewQueueDiscipline(_) => RTM_NEWQDISC,
538            DelQueueDiscipline(_) => RTM_DELQDISC,
539            GetQueueDiscipline(_) => RTM_GETQDISC,
540            NewTrafficClass(_) => RTM_NEWTCLASS,
541            DelTrafficClass(_) => RTM_DELTCLASS,
542            GetTrafficClass(_) => RTM_GETTCLASS,
543            NewTrafficFilter(_) => RTM_NEWTFILTER,
544            DelTrafficFilter(_) => RTM_DELTFILTER,
545            GetTrafficFilter(_) => RTM_GETTFILTER,
546            NewTrafficChain(_) => RTM_NEWCHAIN,
547            DelTrafficChain(_) => RTM_DELCHAIN,
548            GetTrafficChain(_) => RTM_GETCHAIN,
549            GetNsId(_) => RTM_GETNSID,
550            NewNsId(_) => RTM_NEWNSID,
551            DelNsId(_) => RTM_DELNSID,
552            GetRule(_) => RTM_GETRULE,
553            NewRule(_) => RTM_NEWRULE,
554            DelRule(_) => RTM_DELRULE,
555        }
556    }
557}
558
559impl Emitable for RouteNetlinkMessage {
560    #[rustfmt::skip]
561    fn buffer_len(&self) -> usize {
562        use self::RouteNetlinkMessage::*;
563        match self {
564            | NewLink(ref msg)
565            | DelLink(ref msg)
566            | GetLink(ref msg)
567            | SetLink(ref msg)
568            | NewLinkProp(ref msg)
569            | DelLinkProp(ref msg)
570            =>  msg.buffer_len(),
571
572            | NewAddress(ref msg)
573            | DelAddress(ref msg)
574            | GetAddress(ref msg)
575            => msg.buffer_len(),
576
577            | NewNeighbour(ref msg)
578            | GetNeighbour(ref msg)
579            | DelNeighbour(ref msg)
580            => msg.buffer_len(),
581
582            | NewNeighbourTable(ref msg)
583            | GetNeighbourTable(ref msg)
584            | SetNeighbourTable(ref msg)
585            => msg.buffer_len(),
586
587            | NewNeighbourDiscoveryUserOption(ref msg) => msg.buffer_len(),
588
589            | NewRoute(ref msg)
590            | DelRoute(ref msg)
591            | GetRoute(ref msg)
592            => msg.buffer_len(),
593
594            NewPrefix(ref msg) => msg.buffer_len(),
595
596            | NewQueueDiscipline(ref msg)
597            | DelQueueDiscipline(ref msg)
598            | GetQueueDiscipline(ref msg)
599            | NewTrafficClass(ref msg)
600            | DelTrafficClass(ref msg)
601            | GetTrafficClass(ref msg)
602            | NewTrafficFilter(ref msg)
603            | DelTrafficFilter(ref msg)
604            | GetTrafficFilter(ref msg)
605            | NewTrafficChain(ref msg)
606            | DelTrafficChain(ref msg)
607            | GetTrafficChain(ref msg)
608            => msg.buffer_len(),
609
610            | NewNsId(ref msg)
611            | DelNsId(ref msg)
612            | GetNsId(ref msg)
613            => msg.buffer_len(),
614
615            | NewRule(ref msg)
616            | DelRule(ref msg)
617            | GetRule(ref msg)
618            => msg.buffer_len()
619        }
620    }
621
622    #[rustfmt::skip]
623    fn emit(&self, buffer: &mut [u8]) {
624        use self::RouteNetlinkMessage::*;
625        match self {
626            | NewLink(ref msg)
627            | DelLink(ref msg)
628            | GetLink(ref msg)
629            | SetLink(ref msg)
630            | NewLinkProp(ref msg)
631            | DelLinkProp(ref msg)
632            => msg.emit(buffer),
633
634            | NewAddress(ref msg)
635            | DelAddress(ref msg)
636            | GetAddress(ref msg)
637            => msg.emit(buffer),
638
639            | GetNeighbour(ref msg)
640            | NewNeighbour(ref msg)
641            | DelNeighbour(ref msg)
642            => msg.emit(buffer),
643
644            | GetNeighbourTable(ref msg)
645            | NewNeighbourTable(ref msg)
646            | SetNeighbourTable(ref msg)
647            => msg.emit(buffer),
648
649            | NewNeighbourDiscoveryUserOption(ref msg) => msg.emit(buffer),
650
651            | NewRoute(ref msg)
652            | DelRoute(ref msg)
653            | GetRoute(ref msg)
654            => msg.emit(buffer),
655
656            | NewPrefix(ref msg) => msg.emit(buffer),
657
658            | NewQueueDiscipline(ref msg)
659            | DelQueueDiscipline(ref msg)
660            | GetQueueDiscipline(ref msg)
661            | NewTrafficClass(ref msg)
662            | DelTrafficClass(ref msg)
663            | GetTrafficClass(ref msg)
664            | NewTrafficFilter(ref msg)
665            | DelTrafficFilter(ref msg)
666            | GetTrafficFilter(ref msg)
667            | NewTrafficChain(ref msg)
668            | DelTrafficChain(ref msg)
669            | GetTrafficChain(ref msg)
670            => msg.emit(buffer),
671
672            | NewNsId(ref msg)
673            | DelNsId(ref msg)
674            | GetNsId(ref msg)
675            => msg.emit(buffer),
676
677            | NewRule(ref msg)
678            | DelRule(ref msg)
679            | GetRule(ref msg)
680            => msg.emit(buffer)
681        }
682    }
683}
684
685impl NetlinkSerializable for RouteNetlinkMessage {
686    fn message_type(&self) -> u16 {
687        self.message_type()
688    }
689
690    fn buffer_len(&self) -> usize {
691        <Self as Emitable>::buffer_len(self)
692    }
693
694    fn serialize(&self, buffer: &mut [u8]) {
695        self.emit(buffer)
696    }
697}
698
699impl NetlinkDeserializable for RouteNetlinkMessage {
700    type Error = RouteNetlinkMessageParseError;
701
702    fn deserialize(header: &NetlinkHeader, payload: &[u8]) -> Result<Self, Self::Error> {
703        let buf = RouteNetlinkMessageBuffer::new(payload);
704        match RouteNetlinkMessage::parse_with_param(&buf, header.message_type) {
705            Err(e) => Err(e),
706            Ok(message) => Ok(message),
707        }
708    }
709}
710
711impl From<RouteNetlinkMessage> for NetlinkPayload<RouteNetlinkMessage> {
712    fn from(message: RouteNetlinkMessage) -> Self {
713        NetlinkPayload::InnerMessage(message)
714    }
715}