netlink_packet_route/
message.rs

1// SPDX-License-Identifier: MIT
2
3use netlink_packet_core::{
4    DecodeError, Emitable, ErrorContext, NetlinkDeserializable, NetlinkHeader,
5    NetlinkPayload, NetlinkSerializable, Parseable, ParseableParametrized,
6};
7
8use crate::{
9    address::{AddressHeader, AddressMessage, AddressMessageBuffer},
10    link::{LinkMessage, LinkMessageBuffer},
11    neighbour::{NeighbourMessage, NeighbourMessageBuffer},
12    neighbour_table::{NeighbourTableMessage, NeighbourTableMessageBuffer},
13    nsid::{NsidMessage, NsidMessageBuffer},
14    prefix::{PrefixMessage, PrefixMessageBuffer},
15    route::{RouteHeader, RouteMessage, RouteMessageBuffer},
16    rule::{RuleMessage, RuleMessageBuffer},
17    tc::{TcActionMessage, TcActionMessageBuffer, TcMessage, TcMessageBuffer},
18};
19
20const RTM_NEWLINK: u16 = 16;
21const RTM_DELLINK: u16 = 17;
22const RTM_GETLINK: u16 = 18;
23const RTM_SETLINK: u16 = 19;
24const RTM_NEWADDR: u16 = 20;
25const RTM_DELADDR: u16 = 21;
26const RTM_GETADDR: u16 = 22;
27const RTM_NEWROUTE: u16 = 24;
28const RTM_DELROUTE: u16 = 25;
29const RTM_GETROUTE: u16 = 26;
30const RTM_NEWNEIGH: u16 = 28;
31const RTM_DELNEIGH: u16 = 29;
32const RTM_GETNEIGH: u16 = 30;
33const RTM_NEWRULE: u16 = 32;
34const RTM_DELRULE: u16 = 33;
35const RTM_GETRULE: u16 = 34;
36const RTM_NEWQDISC: u16 = 36;
37const RTM_DELQDISC: u16 = 37;
38const RTM_GETQDISC: u16 = 38;
39const RTM_NEWTCLASS: u16 = 40;
40const RTM_DELTCLASS: u16 = 41;
41const RTM_GETTCLASS: u16 = 42;
42const RTM_NEWTFILTER: u16 = 44;
43const RTM_DELTFILTER: u16 = 45;
44const RTM_GETTFILTER: u16 = 46;
45const RTM_NEWACTION: u16 = 48;
46const RTM_DELACTION: u16 = 49;
47const RTM_GETACTION: u16 = 50;
48const RTM_NEWPREFIX: u16 = 52;
49// const RTM_GETMULTICAST: u16 = 58;
50// const RTM_GETANYCAST: u16 = 62;
51const RTM_NEWNEIGHTBL: u16 = 64;
52const RTM_GETNEIGHTBL: u16 = 66;
53const RTM_SETNEIGHTBL: u16 = 67;
54// const RTM_NEWNDUSEROPT: u16 = 68;
55// const RTM_NEWADDRLABEL: u16 = 72;
56// const RTM_DELADDRLABEL: u16 = 73;
57// const RTM_GETADDRLABEL: u16 = 74;
58// const RTM_GETDCB: u16 = 78;
59// const RTM_SETDCB: u16 = 79;
60// const RTM_NEWNETCONF: u16 = 80;
61// const RTM_DELNETCONF: u16 = 81;
62// const RTM_GETNETCONF: u16 = 82;
63// const RTM_NEWMDB: u16 = 84;
64// const RTM_DELMDB: u16 = 85;
65// const RTM_GETMDB: u16 = 86;
66const RTM_NEWNSID: u16 = 88;
67const RTM_DELNSID: u16 = 89;
68const RTM_GETNSID: u16 = 90;
69// const RTM_NEWSTATS: u16 = 92;
70// const RTM_GETSTATS: u16 = 94;
71// const RTM_NEWCACHEREPORT: u16 = 96;
72const RTM_NEWCHAIN: u16 = 100;
73const RTM_DELCHAIN: u16 = 101;
74const RTM_GETCHAIN: u16 = 102;
75const RTM_NEWLINKPROP: u16 = 108;
76const RTM_DELLINKPROP: u16 = 109;
77
78buffer!(RouteNetlinkMessageBuffer);
79
80impl<'a, T: AsRef<[u8]> + ?Sized>
81    ParseableParametrized<RouteNetlinkMessageBuffer<&'a T>, u16>
82    for RouteNetlinkMessage
83{
84    fn parse_with_param(
85        buf: &RouteNetlinkMessageBuffer<&'a T>,
86        message_type: u16,
87    ) -> Result<Self, DecodeError> {
88        let message = match message_type {
89            // Link messages
90            RTM_NEWLINK | RTM_GETLINK | RTM_DELLINK | RTM_SETLINK => {
91                let msg = match LinkMessageBuffer::new_checked(&buf.inner()) {
92                    Ok(buf) => LinkMessage::parse(&buf)
93                        .context("invalid link message")?,
94                    // HACK: iproute2 sends invalid RTM_GETLINK message, where
95                    // the header is limited to the
96                    // interface family (1 byte) and 3 bytes of padding.
97                    Err(e) => {
98                        if buf.inner().len() == 4 && message_type == RTM_GETLINK
99                        {
100                            let mut msg = LinkMessage::default();
101                            msg.header.interface_family = buf.inner()[0].into();
102                            msg
103                        } else {
104                            return Err(e);
105                        }
106                    }
107                };
108                match message_type {
109                    RTM_NEWLINK => RouteNetlinkMessage::NewLink(msg),
110                    RTM_GETLINK => RouteNetlinkMessage::GetLink(msg),
111                    RTM_DELLINK => RouteNetlinkMessage::DelLink(msg),
112                    RTM_SETLINK => RouteNetlinkMessage::SetLink(msg),
113                    _ => unreachable!(),
114                }
115            }
116
117            // Address messages
118            RTM_NEWADDR | RTM_GETADDR | RTM_DELADDR => {
119                let msg = match AddressMessageBuffer::new_checked(&buf.inner())
120                {
121                    Ok(buf) => AddressMessage::parse(&buf)
122                        .context("invalid link message")?,
123                    // HACK: iproute2 sends invalid RTM_GETADDR message, where
124                    // the header is limited to the
125                    // interface family (1 byte) and 3 bytes of padding.
126                    Err(e) => {
127                        if buf.inner().len() == 4 && message_type == RTM_GETADDR
128                        {
129                            let mut msg = AddressMessage {
130                                header: AddressHeader::default(),
131                                attributes: vec![],
132                            };
133                            msg.header.family = buf.inner()[0].into();
134                            msg
135                        } else {
136                            return Err(e);
137                        }
138                    }
139                };
140                match message_type {
141                    RTM_NEWADDR => RouteNetlinkMessage::NewAddress(msg),
142                    RTM_GETADDR => RouteNetlinkMessage::GetAddress(msg),
143                    RTM_DELADDR => RouteNetlinkMessage::DelAddress(msg),
144                    _ => unreachable!(),
145                }
146            }
147
148            // Neighbour messages
149            RTM_NEWNEIGH | RTM_GETNEIGH | RTM_DELNEIGH => {
150                let err = "invalid neighbour message";
151                let msg = NeighbourMessage::parse(
152                    &NeighbourMessageBuffer::new_checked(&buf.inner())
153                        .context(err)?,
154                )
155                .context(err)?;
156                match message_type {
157                    RTM_GETNEIGH => RouteNetlinkMessage::GetNeighbour(msg),
158                    RTM_NEWNEIGH => RouteNetlinkMessage::NewNeighbour(msg),
159                    RTM_DELNEIGH => RouteNetlinkMessage::DelNeighbour(msg),
160                    _ => unreachable!(),
161                }
162            }
163
164            // Neighbour table messages
165            RTM_NEWNEIGHTBL | RTM_GETNEIGHTBL | RTM_SETNEIGHTBL => {
166                let err = "invalid neighbour table message";
167                let msg = NeighbourTableMessage::parse(
168                    &NeighbourTableMessageBuffer::new_checked(&buf.inner())
169                        .context(err)?,
170                )
171                .context(err)?;
172                match message_type {
173                    RTM_GETNEIGHTBL => {
174                        RouteNetlinkMessage::GetNeighbourTable(msg)
175                    }
176                    RTM_NEWNEIGHTBL => {
177                        RouteNetlinkMessage::NewNeighbourTable(msg)
178                    }
179                    RTM_SETNEIGHTBL => {
180                        RouteNetlinkMessage::SetNeighbourTable(msg)
181                    }
182                    _ => unreachable!(),
183                }
184            }
185
186            // Route messages
187            RTM_NEWROUTE | RTM_GETROUTE | RTM_DELROUTE => {
188                let msg = match RouteMessageBuffer::new_checked(&buf.inner()) {
189                    Ok(buf) => RouteMessage::parse(&buf)
190                        .context("invalid route message")?,
191                    // HACK: iproute2 sends invalid RTM_GETROUTE message, where
192                    // the header is limited to the
193                    // interface family (1 byte) and 3 bytes of padding.
194                    Err(e) => {
195                        // Not only does iproute2 sends invalid messages, it's
196                        // also inconsistent in
197                        // doing so: for link and address messages, the length
198                        // advertised in the
199                        // netlink header includes the 3 bytes of padding but it
200                        // does not seem to be the case
201                        // for the route message, hence the buf.length() == 1
202                        // check.
203                        if (buf.inner().len() == 4 || buf.inner().len() == 1)
204                            && message_type == RTM_GETROUTE
205                        {
206                            let mut msg = RouteMessage {
207                                header: RouteHeader::default(),
208                                attributes: vec![],
209                            };
210                            msg.header.address_family = buf.inner()[0].into();
211                            msg
212                        } else {
213                            return Err(e);
214                        }
215                    }
216                };
217                match message_type {
218                    RTM_NEWROUTE => RouteNetlinkMessage::NewRoute(msg),
219                    RTM_GETROUTE => RouteNetlinkMessage::GetRoute(msg),
220                    RTM_DELROUTE => RouteNetlinkMessage::DelRoute(msg),
221                    _ => unreachable!(),
222                }
223            }
224
225            // Prefix messages
226            RTM_NEWPREFIX => {
227                let err = "invalid prefix message";
228                RouteNetlinkMessage::NewPrefix(
229                    PrefixMessage::parse(
230                        &PrefixMessageBuffer::new_checked(&buf.inner())
231                            .context(err)?,
232                    )
233                    .context(err)?,
234                )
235            }
236
237            RTM_NEWRULE | RTM_GETRULE | RTM_DELRULE => {
238                let err = "invalid fib rule message";
239                let msg = RuleMessage::parse(
240                    &RuleMessageBuffer::new_checked(&buf.inner())
241                        .context(err)?,
242                )
243                .context(err)?;
244                match message_type {
245                    RTM_NEWRULE => RouteNetlinkMessage::NewRule(msg),
246                    RTM_DELRULE => RouteNetlinkMessage::DelRule(msg),
247                    RTM_GETRULE => RouteNetlinkMessage::GetRule(msg),
248                    _ => unreachable!(),
249                }
250            }
251            // TC Messages
252            RTM_NEWQDISC | RTM_DELQDISC | RTM_GETQDISC | RTM_NEWTCLASS
253            | RTM_DELTCLASS | RTM_GETTCLASS | RTM_NEWTFILTER
254            | RTM_DELTFILTER | RTM_GETTFILTER | RTM_NEWCHAIN | RTM_DELCHAIN
255            | RTM_GETCHAIN => {
256                let err = "invalid tc message";
257                let msg = TcMessage::parse(
258                    &TcMessageBuffer::new_checked(&buf.inner()).context(err)?,
259                )
260                .context(err)?;
261                match message_type {
262                    RTM_NEWQDISC => {
263                        RouteNetlinkMessage::NewQueueDiscipline(msg)
264                    }
265                    RTM_DELQDISC => {
266                        RouteNetlinkMessage::DelQueueDiscipline(msg)
267                    }
268                    RTM_GETQDISC => {
269                        RouteNetlinkMessage::GetQueueDiscipline(msg)
270                    }
271                    RTM_NEWTCLASS => RouteNetlinkMessage::NewTrafficClass(msg),
272                    RTM_DELTCLASS => RouteNetlinkMessage::DelTrafficClass(msg),
273                    RTM_GETTCLASS => RouteNetlinkMessage::GetTrafficClass(msg),
274                    RTM_NEWTFILTER => {
275                        RouteNetlinkMessage::NewTrafficFilter(msg)
276                    }
277                    RTM_DELTFILTER => {
278                        RouteNetlinkMessage::DelTrafficFilter(msg)
279                    }
280                    RTM_GETTFILTER => {
281                        RouteNetlinkMessage::GetTrafficFilter(msg)
282                    }
283                    RTM_NEWCHAIN => RouteNetlinkMessage::NewTrafficChain(msg),
284                    RTM_DELCHAIN => RouteNetlinkMessage::DelTrafficChain(msg),
285                    RTM_GETCHAIN => RouteNetlinkMessage::GetTrafficChain(msg),
286                    _ => unreachable!(),
287                }
288            }
289
290            RTM_NEWACTION | RTM_DELACTION | RTM_GETACTION => {
291                let err = "invalid tc action message";
292                let msg = TcActionMessage::parse(
293                    &TcActionMessageBuffer::new_checked(&buf.inner())
294                        .context(err)?,
295                )
296                .context(err)?;
297                match message_type {
298                    RTM_NEWACTION => RouteNetlinkMessage::NewTrafficAction(msg),
299                    RTM_DELACTION => RouteNetlinkMessage::DelTrafficAction(msg),
300                    RTM_GETACTION => RouteNetlinkMessage::GetTrafficAction(msg),
301                    _ => unreachable!(),
302                }
303            }
304
305            // ND ID Messages
306            RTM_NEWNSID | RTM_GETNSID | RTM_DELNSID => {
307                let err = "invalid nsid message";
308                let msg = NsidMessage::parse(
309                    &NsidMessageBuffer::new_checked(&buf.inner())
310                        .context(err)?,
311                )
312                .context(err)?;
313                match message_type {
314                    RTM_NEWNSID => RouteNetlinkMessage::NewNsId(msg),
315                    RTM_DELNSID => RouteNetlinkMessage::DelNsId(msg),
316                    RTM_GETNSID => RouteNetlinkMessage::GetNsId(msg),
317                    _ => unreachable!(),
318                }
319            }
320
321            _ => {
322                return Err(
323                    format!("Unknown message type: {message_type}").into()
324                )
325            }
326        };
327        Ok(message)
328    }
329}
330
331#[derive(Debug, PartialEq, Eq, Clone)]
332#[non_exhaustive]
333pub enum RouteNetlinkMessage {
334    NewLink(LinkMessage),
335    DelLink(LinkMessage),
336    GetLink(LinkMessage),
337    SetLink(LinkMessage),
338    NewLinkProp(LinkMessage),
339    DelLinkProp(LinkMessage),
340    NewAddress(AddressMessage),
341    DelAddress(AddressMessage),
342    GetAddress(AddressMessage),
343    NewNeighbour(NeighbourMessage),
344    GetNeighbour(NeighbourMessage),
345    DelNeighbour(NeighbourMessage),
346    NewNeighbourTable(NeighbourTableMessage),
347    GetNeighbourTable(NeighbourTableMessage),
348    SetNeighbourTable(NeighbourTableMessage),
349    NewRoute(RouteMessage),
350    DelRoute(RouteMessage),
351    GetRoute(RouteMessage),
352    NewPrefix(PrefixMessage),
353    NewQueueDiscipline(TcMessage),
354    DelQueueDiscipline(TcMessage),
355    GetQueueDiscipline(TcMessage),
356    NewTrafficClass(TcMessage),
357    DelTrafficClass(TcMessage),
358    GetTrafficClass(TcMessage),
359    NewTrafficFilter(TcMessage),
360    DelTrafficFilter(TcMessage),
361    GetTrafficFilter(TcMessage),
362    NewTrafficAction(TcActionMessage),
363    DelTrafficAction(TcActionMessage),
364    GetTrafficAction(TcActionMessage),
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_action(&self) -> bool {
478        matches!(self, RouteNetlinkMessage::NewTrafficAction(_))
479    }
480
481    pub fn is_del_action(&self) -> bool {
482        matches!(self, RouteNetlinkMessage::DelTrafficAction(_))
483    }
484
485    pub fn is_get_action(&self) -> bool {
486        matches!(self, RouteNetlinkMessage::GetTrafficAction(_))
487    }
488
489    pub fn is_new_chain(&self) -> bool {
490        matches!(self, RouteNetlinkMessage::NewTrafficChain(_))
491    }
492
493    pub fn is_del_chain(&self) -> bool {
494        matches!(self, RouteNetlinkMessage::DelTrafficChain(_))
495    }
496
497    pub fn is_get_chain(&self) -> bool {
498        matches!(self, RouteNetlinkMessage::GetTrafficChain(_))
499    }
500
501    pub fn is_new_nsid(&self) -> bool {
502        matches!(self, RouteNetlinkMessage::NewNsId(_))
503    }
504
505    pub fn is_get_nsid(&self) -> bool {
506        matches!(self, RouteNetlinkMessage::GetNsId(_))
507    }
508
509    pub fn is_del_nsid(&self) -> bool {
510        matches!(self, RouteNetlinkMessage::DelNsId(_))
511    }
512
513    pub fn is_get_rule(&self) -> bool {
514        matches!(self, RouteNetlinkMessage::GetRule(_))
515    }
516
517    pub fn is_new_rule(&self) -> bool {
518        matches!(self, RouteNetlinkMessage::NewRule(_))
519    }
520
521    pub fn is_del_rule(&self) -> bool {
522        matches!(self, RouteNetlinkMessage::DelRule(_))
523    }
524
525    pub fn message_type(&self) -> u16 {
526        use self::RouteNetlinkMessage::*;
527
528        match self {
529            NewLink(_) => RTM_NEWLINK,
530            DelLink(_) => RTM_DELLINK,
531            GetLink(_) => RTM_GETLINK,
532            SetLink(_) => RTM_SETLINK,
533            NewLinkProp(_) => RTM_NEWLINKPROP,
534            DelLinkProp(_) => RTM_DELLINKPROP,
535            NewAddress(_) => RTM_NEWADDR,
536            DelAddress(_) => RTM_DELADDR,
537            GetAddress(_) => RTM_GETADDR,
538            GetNeighbour(_) => RTM_GETNEIGH,
539            NewNeighbour(_) => RTM_NEWNEIGH,
540            DelNeighbour(_) => RTM_DELNEIGH,
541            GetNeighbourTable(_) => RTM_GETNEIGHTBL,
542            NewNeighbourTable(_) => RTM_NEWNEIGHTBL,
543            SetNeighbourTable(_) => RTM_SETNEIGHTBL,
544            NewRoute(_) => RTM_NEWROUTE,
545            DelRoute(_) => RTM_DELROUTE,
546            GetRoute(_) => RTM_GETROUTE,
547            NewPrefix(_) => RTM_NEWPREFIX,
548            NewQueueDiscipline(_) => RTM_NEWQDISC,
549            DelQueueDiscipline(_) => RTM_DELQDISC,
550            GetQueueDiscipline(_) => RTM_GETQDISC,
551            NewTrafficClass(_) => RTM_NEWTCLASS,
552            DelTrafficClass(_) => RTM_DELTCLASS,
553            GetTrafficClass(_) => RTM_GETTCLASS,
554            NewTrafficFilter(_) => RTM_NEWTFILTER,
555            DelTrafficFilter(_) => RTM_DELTFILTER,
556            GetTrafficFilter(_) => RTM_GETTFILTER,
557            NewTrafficAction(_) => RTM_NEWACTION,
558            DelTrafficAction(_) => RTM_DELACTION,
559            GetTrafficAction(_) => RTM_GETACTION,
560            NewTrafficChain(_) => RTM_NEWCHAIN,
561            DelTrafficChain(_) => RTM_DELCHAIN,
562            GetTrafficChain(_) => RTM_GETCHAIN,
563            GetNsId(_) => RTM_GETNSID,
564            NewNsId(_) => RTM_NEWNSID,
565            DelNsId(_) => RTM_DELNSID,
566            GetRule(_) => RTM_GETRULE,
567            NewRule(_) => RTM_NEWRULE,
568            DelRule(_) => RTM_DELRULE,
569        }
570    }
571}
572
573impl Emitable for RouteNetlinkMessage {
574    #[rustfmt::skip]
575    fn buffer_len(&self) -> usize {
576        use self::RouteNetlinkMessage::*;
577        match self {
578            | NewLink(ref msg)
579            | DelLink(ref msg)
580            | GetLink(ref msg)
581            | SetLink(ref msg)
582            | NewLinkProp(ref msg)
583            | DelLinkProp(ref msg)
584            =>  msg.buffer_len(),
585
586            | NewAddress(ref msg)
587            | DelAddress(ref msg)
588            | GetAddress(ref msg)
589            => msg.buffer_len(),
590
591            | NewNeighbour(ref msg)
592            | GetNeighbour(ref msg)
593            | DelNeighbour(ref msg)
594            => msg.buffer_len(),
595
596            | NewNeighbourTable(ref msg)
597            | GetNeighbourTable(ref msg)
598            | SetNeighbourTable(ref msg)
599            => msg.buffer_len(),
600
601            | NewRoute(ref msg)
602            | DelRoute(ref msg)
603            | GetRoute(ref msg)
604            => msg.buffer_len(),
605
606            NewPrefix(ref msg) => msg.buffer_len(),
607
608            | NewQueueDiscipline(ref msg)
609            | DelQueueDiscipline(ref msg)
610            | GetQueueDiscipline(ref msg)
611            | NewTrafficClass(ref msg)
612            | DelTrafficClass(ref msg)
613            | GetTrafficClass(ref msg)
614            | NewTrafficFilter(ref msg)
615            | DelTrafficFilter(ref msg)
616            | GetTrafficFilter(ref msg)
617            | NewTrafficChain(ref msg)
618            | DelTrafficChain(ref msg)
619            | GetTrafficChain(ref msg)
620            => msg.buffer_len(),
621
622            | NewNsId(ref msg)
623            | DelNsId(ref msg)
624            | GetNsId(ref msg)
625            => msg.buffer_len(),
626
627            | NewRule(ref msg)
628            | DelRule(ref msg)
629            | GetRule(ref msg)
630            => msg.buffer_len(),
631
632            | NewTrafficAction(ref msg)
633            | DelTrafficAction(ref msg)
634            | GetTrafficAction(ref msg)
635            => msg.buffer_len(),
636        }
637    }
638
639    #[rustfmt::skip]
640    fn emit(&self, buffer: &mut [u8]) {
641        use self::RouteNetlinkMessage::*;
642        match self {
643            | NewLink(ref msg)
644            | DelLink(ref msg)
645            | GetLink(ref msg)
646            | SetLink(ref msg)
647            | NewLinkProp(ref msg)
648            | DelLinkProp(ref msg)
649            => msg.emit(buffer),
650
651            | NewAddress(ref msg)
652            | DelAddress(ref msg)
653            | GetAddress(ref msg)
654            => msg.emit(buffer),
655
656            | GetNeighbour(ref msg)
657            | NewNeighbour(ref msg)
658            | DelNeighbour(ref msg)
659            => msg.emit(buffer),
660
661            | GetNeighbourTable(ref msg)
662            | NewNeighbourTable(ref msg)
663            | SetNeighbourTable(ref msg)
664            => msg.emit(buffer),
665
666            | NewRoute(ref msg)
667            | DelRoute(ref msg)
668            | GetRoute(ref msg)
669            => msg.emit(buffer),
670
671            | NewPrefix(ref msg) => msg.emit(buffer),
672
673            | NewQueueDiscipline(ref msg)
674            | DelQueueDiscipline(ref msg)
675            | GetQueueDiscipline(ref msg)
676            | NewTrafficClass(ref msg)
677            | DelTrafficClass(ref msg)
678            | GetTrafficClass(ref msg)
679            | NewTrafficFilter(ref msg)
680            | DelTrafficFilter(ref msg)
681            | GetTrafficFilter(ref msg)
682            | NewTrafficChain(ref msg)
683            | DelTrafficChain(ref msg)
684            | GetTrafficChain(ref msg)
685            => msg.emit(buffer),
686
687            | NewNsId(ref msg)
688            | DelNsId(ref msg)
689            | GetNsId(ref msg)
690            => msg.emit(buffer),
691
692            | NewRule(ref msg)
693            | DelRule(ref msg)
694            | GetRule(ref msg)
695            => msg.emit(buffer),
696
697            | NewTrafficAction(ref msg)
698            | DelTrafficAction(ref msg)
699            | GetTrafficAction(ref msg)
700            => msg.emit(buffer),
701        }
702    }
703}
704
705impl NetlinkSerializable for RouteNetlinkMessage {
706    fn message_type(&self) -> u16 {
707        self.message_type()
708    }
709
710    fn buffer_len(&self) -> usize {
711        <Self as Emitable>::buffer_len(self)
712    }
713
714    fn serialize(&self, buffer: &mut [u8]) {
715        self.emit(buffer)
716    }
717}
718
719impl NetlinkDeserializable for RouteNetlinkMessage {
720    type Error = DecodeError;
721    fn deserialize(
722        header: &NetlinkHeader,
723        payload: &[u8],
724    ) -> Result<Self, Self::Error> {
725        let buf = RouteNetlinkMessageBuffer::new(payload);
726        match RouteNetlinkMessage::parse_with_param(&buf, header.message_type) {
727            Err(e) => Err(e),
728            Ok(message) => Ok(message),
729        }
730    }
731}
732
733impl From<RouteNetlinkMessage> for NetlinkPayload<RouteNetlinkMessage> {
734    fn from(message: RouteNetlinkMessage) -> Self {
735        NetlinkPayload::InnerMessage(message)
736    }
737}