netlink_packet_route/rtnl/
buffer.rs1use anyhow::Context;
4use netlink_packet_utils::{
5 traits::{Parseable, ParseableParametrized},
6 DecodeError,
7};
8
9use crate::{
10 constants::*, AddressHeader, AddressMessage, AddressMessageBuffer,
11 LinkMessage, LinkMessageBuffer, NeighbourMessage, NeighbourMessageBuffer,
12 NeighbourTableMessage, NeighbourTableMessageBuffer, NsidMessage,
13 NsidMessageBuffer, RouteHeader, RouteMessage, RouteMessageBuffer,
14 RtnlMessage, RuleMessage, RuleMessageBuffer, TcMessage, TcMessageBuffer,
15};
16
17buffer!(RtnlMessageBuffer);
18
19impl<'a, T: AsRef<[u8]> + ?Sized>
20 ParseableParametrized<RtnlMessageBuffer<&'a T>, u16> for RtnlMessage
21{
22 #[rustfmt::skip]
23 fn parse_with_param(buf: &RtnlMessageBuffer<&'a T>, message_type: u16) -> Result<Self, DecodeError> {
24 use self::RtnlMessage::*;
25 let message = match message_type {
26
27 RTM_NEWLINK | RTM_GETLINK | RTM_DELLINK | RTM_SETLINK => {
29 let msg = match LinkMessageBuffer::new_checked(&buf.inner()) {
30 Ok(buf) => LinkMessage::parse(&buf).context("invalid link message")?,
31 Err(e) => {
34 if buf.inner().len() == 4 && message_type == RTM_GETLINK {
35 let mut msg = LinkMessage::default();
36 msg.header.interface_family = buf.inner()[0];
37 msg
38 } else {
39 return Err(e);
40 }
41 }
42 };
43 match message_type {
44 RTM_NEWLINK => NewLink(msg),
45 RTM_GETLINK => GetLink(msg),
46 RTM_DELLINK => DelLink(msg),
47 RTM_SETLINK => SetLink(msg),
48 _ => unreachable!(),
49 }
50 }
51
52 RTM_NEWADDR | RTM_GETADDR | RTM_DELADDR => {
54 let msg = match AddressMessageBuffer::new_checked(&buf.inner()) {
55 Ok(buf) => AddressMessage::parse(&buf).context("invalid link message")?,
56 Err(e) => {
59 if buf.inner().len() == 4 && message_type == RTM_GETADDR {
60 let mut msg = AddressMessage {
61 header: AddressHeader::default(),
62 nlas: vec![],
63 };
64 msg.header.family = buf.inner()[0];
65 msg
66 } else {
67 return Err(e);
68 }
69 }
70 };
71 match message_type {
72 RTM_NEWADDR => NewAddress(msg),
73 RTM_GETADDR => GetAddress(msg),
74 RTM_DELADDR => DelAddress(msg),
75 _ => unreachable!(),
76 }
77 }
78
79 RTM_NEWNEIGH | RTM_GETNEIGH | RTM_DELNEIGH => {
81 let err = "invalid neighbour message";
82 let msg = NeighbourMessage::parse(&NeighbourMessageBuffer::new_checked(&buf.inner()).context(err)?).context(err)?;
83 match message_type {
84 RTM_GETNEIGH => GetNeighbour(msg),
85 RTM_NEWNEIGH => NewNeighbour(msg),
86 RTM_DELNEIGH => DelNeighbour(msg),
87 _ => unreachable!(),
88 }
89 }
90
91 RTM_NEWNEIGHTBL | RTM_GETNEIGHTBL | RTM_SETNEIGHTBL => {
93 let err = "invalid neighbour table message";
94 let msg = NeighbourTableMessage::parse(&NeighbourTableMessageBuffer::new_checked(&buf.inner()).context(err)?).context(err)?;
95 match message_type {
96 RTM_GETNEIGHTBL => GetNeighbourTable(msg),
97 RTM_NEWNEIGHTBL => NewNeighbourTable(msg),
98 RTM_SETNEIGHTBL => SetNeighbourTable(msg),
99 _ => unreachable!(),
100 }
101 }
102
103 RTM_NEWROUTE | RTM_GETROUTE | RTM_DELROUTE => {
105 let msg = match RouteMessageBuffer::new_checked(&buf.inner()) {
106 Ok(buf) => RouteMessage::parse(&buf).context("invalid route message")?,
107 Err(e) => {
110 if (buf.inner().len() == 4 || buf.inner().len() == 1) && message_type == RTM_GETROUTE {
115 let mut msg = RouteMessage {
116 header: RouteHeader::default(),
117 nlas: vec![],
118 };
119 msg.header.address_family = buf.inner()[0];
120 msg
121 } else {
122 return Err(e);
123 }
124 }
125 };
126 match message_type {
127 RTM_NEWROUTE => NewRoute(msg),
128 RTM_GETROUTE => GetRoute(msg),
129 RTM_DELROUTE => DelRoute(msg),
130 _ => unreachable!(),
131 }
132 }
133
134 RTM_NEWRULE | RTM_GETRULE | RTM_DELRULE => {
135 let err = "invalid fib rule message";
136 let msg = RuleMessage::parse(&RuleMessageBuffer::new_checked(&buf.inner()).context(err)?).context(err)?;
137 match message_type {
138 RTM_NEWRULE => NewRule(msg),
139 RTM_DELRULE => DelRule(msg),
140 RTM_GETRULE => GetRule(msg),
141 _ => unreachable!()
142 }
143 }
144 RTM_NEWQDISC | RTM_DELQDISC | RTM_GETQDISC |
146 RTM_NEWTCLASS | RTM_DELTCLASS | RTM_GETTCLASS |
147 RTM_NEWTFILTER | RTM_DELTFILTER | RTM_GETTFILTER |
148 RTM_NEWCHAIN | RTM_DELCHAIN | RTM_GETCHAIN => {
149 let err = "invalid tc message";
150 let msg = TcMessage::parse(&TcMessageBuffer::new_checked(&buf.inner()).context(err)?).context(err)?;
151 match message_type {
152 RTM_NEWQDISC => NewQueueDiscipline(msg),
153 RTM_DELQDISC => DelQueueDiscipline(msg),
154 RTM_GETQDISC => GetQueueDiscipline(msg),
155 RTM_NEWTCLASS => NewTrafficClass(msg),
156 RTM_DELTCLASS => DelTrafficClass(msg),
157 RTM_GETTCLASS => GetTrafficClass(msg),
158 RTM_NEWTFILTER => NewTrafficFilter(msg),
159 RTM_DELTFILTER => DelTrafficFilter(msg),
160 RTM_GETTFILTER => GetTrafficFilter(msg),
161 RTM_NEWCHAIN => NewTrafficChain(msg),
162 RTM_DELCHAIN => DelTrafficChain(msg),
163 RTM_GETCHAIN => GetTrafficChain(msg),
164 _ => unreachable!(),
165 }
166 }
167
168 RTM_NEWNSID | RTM_GETNSID | RTM_DELNSID => {
170 let err = "invalid nsid message";
171 let msg = NsidMessage::parse(&NsidMessageBuffer::new_checked(&buf.inner()).context(err)?).context(err)?;
172 match message_type {
173 RTM_NEWNSID => NewNsId(msg),
174 RTM_DELNSID => DelNsId(msg),
175 RTM_GETNSID => GetNsId(msg),
176 _ => unreachable!(),
177 }
178 }
179
180 _ => return Err(format!("Unknown message type: {message_type}").into()),
181 };
182 Ok(message)
183 }
184}