1use netlink_packet_core::{
4 DecodeError, DefaultNla, Emitable, ErrorContext, Nla, NlaBuffer,
5 NlasIterator, Parseable,
6};
7
8use super::super::buffer_tool::expand_buffer_if_small;
9
10const IFLA_INET_CONF: u16 = 1;
11const __IPV4_DEVCONF_MAX: usize = 34;
13const IPV4_DEVCONF_MAX: usize = __IPV4_DEVCONF_MAX - 1;
14const DEV_CONF_LEN: usize = IPV4_DEVCONF_MAX * 4;
15
16#[derive(Clone, Eq, PartialEq, Debug)]
17#[non_exhaustive]
18pub enum AfSpecInet {
19 DevConf(InetDevConf),
20 Other(DefaultNla),
21}
22
23pub(crate) struct VecAfSpecInet(pub(crate) Vec<AfSpecInet>);
24
25impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
26 for VecAfSpecInet
27{
28 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
29 let mut nlas = vec![];
30 let err = "Invalid AF_INET NLA for IFLA_AF_SPEC(AF_UNSPEC)";
31 for nla in NlasIterator::new(buf.into_inner()) {
32 let nla = nla.context(err)?;
33 nlas.push(AfSpecInet::parse(&nla)?);
34 }
35 Ok(Self(nlas))
36 }
37}
38
39impl Nla for AfSpecInet {
40 fn value_len(&self) -> usize {
41 use self::AfSpecInet::*;
42 match *self {
43 DevConf(ref c) => c.buffer_len(),
44 Other(ref nla) => nla.value_len(),
45 }
46 }
47
48 fn emit_value(&self, buffer: &mut [u8]) {
49 use self::AfSpecInet::*;
50 match *self {
51 DevConf(ref c) => c.emit(buffer),
52 Other(ref nla) => nla.emit_value(buffer),
53 }
54 }
55
56 fn kind(&self) -> u16 {
57 use self::AfSpecInet::*;
58 match *self {
59 DevConf(_) => IFLA_INET_CONF,
60 Other(ref nla) => nla.kind(),
61 }
62 }
63}
64
65impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for AfSpecInet {
66 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
67 use self::AfSpecInet::*;
68
69 let payload = buf.value();
70 Ok(match buf.kind() {
71 IFLA_INET_CONF => {
72 DevConf(InetDevConf::parse(&InetDevConfBuffer::new(
73 expand_buffer_if_small(
74 payload,
75 DEV_CONF_LEN,
76 "IFLA_INET_CONF",
77 )
78 .as_slice(),
79 ))?)
80 }
81 kind => Other(DefaultNla::parse(buf).context(format!(
82 "Unknown NLA type {kind} for IFLA_AF_SPEC(inet)"
83 ))?),
84 })
85 }
86}
87
88buffer!(InetDevConfBuffer(DEV_CONF_LEN) {
89 forwarding: (i32, 0..4),
90 mc_forwarding: (i32, 4..8),
91 proxy_arp: (i32, 8..12),
92 accept_redirects: (i32, 12..16),
93 secure_redirects: (i32, 16..20),
94 send_redirects: (i32, 20..24),
95 shared_media: (i32, 24..28),
96 rp_filter: (i32, 28..32),
97 accept_source_route: (i32, 32..36),
98 bootp_relay: (i32, 36..40),
99 log_martians: (i32, 40..44),
100 tag: (i32, 44..48),
101 arpfilter: (i32, 48..52),
102 medium_id: (i32, 52..56),
103 noxfrm: (i32, 56..60),
104 nopolicy: (i32, 60..64),
105 force_igmp_version: (i32, 64..68),
106 arp_announce: (i32, 68..72),
107 arp_ignore: (i32, 72..76),
108 promote_secondaries: (i32, 76..80),
109 arp_accept: (i32, 80..84),
110 arp_notify: (i32, 84..88),
111 accept_local: (i32, 88..92),
112 src_vmark: (i32, 92..96),
113 proxy_arp_pvlan: (i32, 96..100),
114 route_localnet: (i32, 100..104),
115 igmpv2_unsolicited_report_interval: (i32, 104..108),
116 igmpv3_unsolicited_report_interval: (i32, 108..112),
117 ignore_routes_with_linkdown: (i32, 112..116),
118 drop_unicast_in_l2_multicast: (i32, 116..120),
119 drop_gratuitous_arp: (i32, 120..124),
120 bc_forwarding: (i32, 124..128),
121 arp_evict_nocarrier: (i32, 128..132),
122});
123
124#[derive(Clone, Copy, Eq, PartialEq, Debug, Default)]
125#[non_exhaustive]
126pub struct InetDevConf {
127 pub forwarding: i32,
128 pub mc_forwarding: i32,
129 pub proxy_arp: i32,
130 pub accept_redirects: i32,
131 pub secure_redirects: i32,
132 pub send_redirects: i32,
133 pub shared_media: i32,
134 pub rp_filter: i32,
135 pub accept_source_route: i32,
136 pub bootp_relay: i32,
137 pub log_martians: i32,
138 pub tag: i32,
139 pub arpfilter: i32,
140 pub medium_id: i32,
141 pub noxfrm: i32,
142 pub nopolicy: i32,
143 pub force_igmp_version: i32,
144 pub arp_announce: i32,
145 pub arp_ignore: i32,
146 pub promote_secondaries: i32,
147 pub arp_accept: i32,
148 pub arp_notify: i32,
149 pub accept_local: i32,
150 pub src_vmark: i32,
151 pub proxy_arp_pvlan: i32,
152 pub route_localnet: i32,
153 pub igmpv2_unsolicited_report_interval: i32,
154 pub igmpv3_unsolicited_report_interval: i32,
155 pub ignore_routes_with_linkdown: i32,
156 pub drop_unicast_in_l2_multicast: i32,
157 pub drop_gratuitous_arp: i32,
158 pub bc_forwarding: i32,
159 pub arp_evict_nocarrier: i32,
160}
161
162impl<T: AsRef<[u8]>> Parseable<InetDevConfBuffer<T>> for InetDevConf {
163 fn parse(buf: &InetDevConfBuffer<T>) -> Result<Self, DecodeError> {
164 Ok(Self {
165 forwarding: buf.forwarding(),
166 mc_forwarding: buf.mc_forwarding(),
167 proxy_arp: buf.proxy_arp(),
168 accept_redirects: buf.accept_redirects(),
169 secure_redirects: buf.secure_redirects(),
170 send_redirects: buf.send_redirects(),
171 shared_media: buf.shared_media(),
172 rp_filter: buf.rp_filter(),
173 accept_source_route: buf.accept_source_route(),
174 bootp_relay: buf.bootp_relay(),
175 log_martians: buf.log_martians(),
176 tag: buf.tag(),
177 arpfilter: buf.arpfilter(),
178 medium_id: buf.medium_id(),
179 noxfrm: buf.noxfrm(),
180 nopolicy: buf.nopolicy(),
181 force_igmp_version: buf.force_igmp_version(),
182 arp_announce: buf.arp_announce(),
183 arp_ignore: buf.arp_ignore(),
184 promote_secondaries: buf.promote_secondaries(),
185 arp_accept: buf.arp_accept(),
186 arp_notify: buf.arp_notify(),
187 accept_local: buf.accept_local(),
188 src_vmark: buf.src_vmark(),
189 proxy_arp_pvlan: buf.proxy_arp_pvlan(),
190 route_localnet: buf.route_localnet(),
191 igmpv2_unsolicited_report_interval: buf
192 .igmpv2_unsolicited_report_interval(),
193 igmpv3_unsolicited_report_interval: buf
194 .igmpv3_unsolicited_report_interval(),
195 ignore_routes_with_linkdown: buf.ignore_routes_with_linkdown(),
196 drop_unicast_in_l2_multicast: buf.drop_unicast_in_l2_multicast(),
197 drop_gratuitous_arp: buf.drop_gratuitous_arp(),
198 bc_forwarding: buf.bc_forwarding(),
199 arp_evict_nocarrier: buf.arp_evict_nocarrier(),
200 })
201 }
202}
203
204impl Emitable for InetDevConf {
205 fn buffer_len(&self) -> usize {
206 DEV_CONF_LEN
207 }
208
209 fn emit(&self, buffer: &mut [u8]) {
210 let mut buffer = InetDevConfBuffer::new(buffer);
211 buffer.set_forwarding(self.forwarding);
212 buffer.set_mc_forwarding(self.mc_forwarding);
213 buffer.set_proxy_arp(self.proxy_arp);
214 buffer.set_accept_redirects(self.accept_redirects);
215 buffer.set_secure_redirects(self.secure_redirects);
216 buffer.set_send_redirects(self.send_redirects);
217 buffer.set_shared_media(self.shared_media);
218 buffer.set_rp_filter(self.rp_filter);
219 buffer.set_accept_source_route(self.accept_source_route);
220 buffer.set_bootp_relay(self.bootp_relay);
221 buffer.set_log_martians(self.log_martians);
222 buffer.set_tag(self.tag);
223 buffer.set_arpfilter(self.arpfilter);
224 buffer.set_medium_id(self.medium_id);
225 buffer.set_noxfrm(self.noxfrm);
226 buffer.set_nopolicy(self.nopolicy);
227 buffer.set_force_igmp_version(self.force_igmp_version);
228 buffer.set_arp_announce(self.arp_announce);
229 buffer.set_arp_ignore(self.arp_ignore);
230 buffer.set_promote_secondaries(self.promote_secondaries);
231 buffer.set_arp_accept(self.arp_accept);
232 buffer.set_arp_notify(self.arp_notify);
233 buffer.set_accept_local(self.accept_local);
234 buffer.set_src_vmark(self.src_vmark);
235 buffer.set_proxy_arp_pvlan(self.proxy_arp_pvlan);
236 buffer.set_route_localnet(self.route_localnet);
237 buffer.set_igmpv2_unsolicited_report_interval(
238 self.igmpv2_unsolicited_report_interval,
239 );
240 buffer.set_igmpv3_unsolicited_report_interval(
241 self.igmpv3_unsolicited_report_interval,
242 );
243 buffer
244 .set_ignore_routes_with_linkdown(self.ignore_routes_with_linkdown);
245 buffer.set_drop_unicast_in_l2_multicast(
246 self.drop_unicast_in_l2_multicast,
247 );
248 buffer.set_drop_gratuitous_arp(self.drop_gratuitous_arp);
249 buffer.set_bc_forwarding(self.bc_forwarding);
250 buffer.set_arp_evict_nocarrier(self.arp_evict_nocarrier);
251 }
252}