netlink_packet_route/
message.rs

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