netlink_packet_route/link/af_spec/
inet.rs

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