netlink_packet_route/link/link_info/gre/
info_gre.rs1use std::{mem::size_of, net::Ipv4Addr};
4
5use netlink_packet_core::{
6 emit_u16_be, emit_u32_be, parse_u16_be, parse_u32_be, parse_u8,
7 DecodeError, DefaultNla, ErrorContext, Nla, NlaBuffer, Parseable,
8};
9
10use super::{
11 gre_common::{
12 IFLA_GRE_COLLECT_METADATA, IFLA_GRE_ENCAP_DPORT, IFLA_GRE_ENCAP_FLAGS,
13 IFLA_GRE_ENCAP_SPORT, IFLA_GRE_ENCAP_TYPE, IFLA_GRE_FWMARK,
14 IFLA_GRE_IFLAGS, IFLA_GRE_IKEY, IFLA_GRE_LOCAL, IFLA_GRE_OFLAGS,
15 IFLA_GRE_OKEY, IFLA_GRE_PMTUDISC, IFLA_GRE_REMOTE, IFLA_GRE_TOS,
16 IFLA_GRE_TTL,
17 },
18 GreEncapFlags, GreEncapType, GreIOFlags,
19};
20use crate::{
21 ip::parse_ipv4_addr, link::link_info::gre::gre_common::IFLA_GRE_LINK,
22};
23
24#[derive(Debug, PartialEq, Eq, Clone)]
25#[non_exhaustive]
26pub enum InfoGre {
27 Link(u32),
28 IFlags(GreIOFlags),
29 OFlags(GreIOFlags),
30 IKey(u32),
31 OKey(u32),
32 Local(Ipv4Addr),
33 Remote(Ipv4Addr),
34 Ttl(u8),
35 Tos(u8),
36 PathMTUDiscovery(bool),
37 EncapType(GreEncapType),
38 EncapFlags(GreEncapFlags),
39 SourcePort(u16),
40 DestinationPort(u16),
41 CollectMetadata,
42 FwMask(u32),
43 Other(DefaultNla),
44}
45
46impl Nla for InfoGre {
47 fn value_len(&self) -> usize {
48 match self {
49 Self::Link(_) => size_of::<u32>(),
50 Self::IFlags(_) | Self::OFlags(_) => size_of::<u16>(),
51 Self::IKey(_) | Self::OKey(_) => size_of::<u32>(),
52 Self::Local(_) | Self::Remote(_) => size_of::<Ipv4Addr>(),
53 Self::Ttl(_) | Self::Tos(_) | Self::PathMTUDiscovery(_) => {
54 size_of::<u8>()
55 }
56 Self::EncapType(_) => size_of::<u16>(),
57 Self::EncapFlags(_) => size_of::<u16>(),
58 Self::SourcePort(_) | Self::DestinationPort(_) => size_of::<u16>(),
59 Self::CollectMetadata => 0,
60 Self::FwMask(_) => size_of::<u32>(),
61 Self::Other(nla) => nla.value_len(),
62 }
63 }
64
65 fn emit_value(&self, buffer: &mut [u8]) {
66 match self {
67 Self::Link(id) => emit_u32_be(buffer, *id).unwrap(),
68 Self::IFlags(flags) | Self::OFlags(flags) => {
69 emit_u16_be(buffer, flags.bits()).unwrap()
70 }
71 Self::IKey(key) | Self::OKey(key) => {
72 emit_u32_be(buffer, *key).unwrap()
73 }
74 Self::Local(ip) | Self::Remote(ip) => {
75 buffer.copy_from_slice(&ip.octets());
76 }
77 Self::Ttl(value) | Self::Tos(value) => buffer[0] = *value,
78 Self::PathMTUDiscovery(discover) => {
79 buffer[0] = if *discover { 1 } else { 0 }
80 }
81 Self::EncapType(t) => emit_u16_be(buffer, t.into()).unwrap(),
82 Self::EncapFlags(flags) => {
83 emit_u16_be(buffer, flags.bits()).unwrap()
84 }
85 Self::SourcePort(port) | Self::DestinationPort(port) => {
86 emit_u16_be(buffer, *port).unwrap()
87 }
88 Self::CollectMetadata => {}
89 Self::FwMask(fw_mask) => emit_u32_be(buffer, *fw_mask).unwrap(),
90 Self::Other(nla) => nla.emit_value(buffer),
91 }
92 }
93
94 fn kind(&self) -> u16 {
95 match self {
96 Self::Link(_) => IFLA_GRE_LINK,
97 Self::IFlags(_) => IFLA_GRE_IFLAGS,
98 Self::OFlags(_) => IFLA_GRE_OFLAGS,
99 Self::IKey(_) => IFLA_GRE_IKEY,
100 Self::Local(_) => IFLA_GRE_LOCAL,
101 Self::Remote(_) => IFLA_GRE_REMOTE,
102 Self::OKey(_) => IFLA_GRE_OKEY,
103 Self::Ttl(_) => IFLA_GRE_TTL,
104 Self::Tos(_) => IFLA_GRE_TOS,
105 Self::PathMTUDiscovery(_) => IFLA_GRE_PMTUDISC,
106 Self::EncapType(_) => IFLA_GRE_ENCAP_TYPE,
107 Self::EncapFlags(_) => IFLA_GRE_ENCAP_FLAGS,
108 Self::SourcePort(_) => IFLA_GRE_ENCAP_SPORT,
109 Self::DestinationPort(_) => IFLA_GRE_ENCAP_DPORT,
110 Self::CollectMetadata => IFLA_GRE_COLLECT_METADATA,
111 Self::FwMask(_) => IFLA_GRE_FWMARK,
112 Self::Other(nla) => nla.kind(),
113 }
114 }
115}
116
117impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoGre {
118 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
119 let payload = buf.value();
120 Ok(match buf.kind() {
121 IFLA_GRE_LINK => Self::Link(
122 parse_u32_be(payload).context("invalid IFLA_GRE_LINK value")?,
123 ),
124 IFLA_GRE_IFLAGS => Self::IFlags(GreIOFlags::from_bits_retain(
125 parse_u16_be(payload)
126 .context("invalid IFLA_GRE_IFLAGS value")?,
127 )),
128 IFLA_GRE_OFLAGS => Self::OFlags(GreIOFlags::from_bits_retain(
129 parse_u16_be(payload)
130 .context("invalid IFLA_GRE_OFLAGS value")?,
131 )),
132 IFLA_GRE_IKEY => Self::IKey(
133 parse_u32_be(payload).context("invalid IFLA_GRE_IKEY value")?,
134 ),
135 IFLA_GRE_OKEY => Self::OKey(
136 parse_u32_be(payload).context("invalid IFLA_GRE_OKEY value")?,
137 ),
138 IFLA_GRE_LOCAL => Self::Local(
139 parse_ipv4_addr(payload)
140 .context("invalid IFLA_GRE_LOCAL value")?,
141 ),
142 IFLA_GRE_REMOTE => Self::Remote(
143 parse_ipv4_addr(payload)
144 .context("invalid IFLA_GRE_LOCAL value")?,
145 ),
146 IFLA_GRE_TTL => Self::Ttl(
147 parse_u8(payload).context("invalid IFLA_GRE_TTL value")?,
148 ),
149 IFLA_GRE_TOS => Self::Tos(
150 parse_u8(payload).context("invalid IFLA_GRE_TOS value")?,
151 ),
152 IFLA_GRE_PMTUDISC => Self::PathMTUDiscovery(
153 parse_u8(payload).context("invalid IFLA_GRE_TOS value")? == 1,
154 ),
155 IFLA_GRE_ENCAP_TYPE => Self::EncapType(GreEncapType::from(
156 parse_u16_be(payload)
157 .context("invalid IFLA_GRE_ENCAP_TYPE value")?,
158 )),
159 IFLA_GRE_ENCAP_FLAGS => {
160 Self::EncapFlags(GreEncapFlags::from_bits_retain(
161 parse_u16_be(payload)
162 .context("invalid IFLA_GRE_ENCAP_FLAGS value")?,
163 ))
164 }
165 IFLA_GRE_ENCAP_SPORT => Self::SourcePort(
166 parse_u16_be(payload)
167 .context("invalid IFLA_GRE_ENCAP_SPORT value")?,
168 ),
169 IFLA_GRE_ENCAP_DPORT => Self::DestinationPort(
170 parse_u16_be(payload)
171 .context("invalid IFLA_GRE_ENCAP_DPORT value")?,
172 ),
173 IFLA_GRE_COLLECT_METADATA => Self::CollectMetadata,
174 IFLA_GRE_FWMARK => Self::FwMask(
175 parse_u32_be(payload)
176 .context("invalid IFLA_GRE_FWMARK value")?,
177 ),
178 kind => Self::Other(
179 DefaultNla::parse(buf)
180 .context(format!("unknown NLA type {kind} for ip6gre"))?,
181 ),
182 })
183 }
184}