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