netlink_packet_route/link/link_info/
macsec.rs1use anyhow::Context;
4use byteorder::{ByteOrder, NativeEndian};
5use netlink_packet_utils::{
6 nla::{DefaultNla, Nla, NlaBuffer},
7 parsers::{parse_u16, parse_u32, parse_u64, parse_u8},
8 traits::Parseable,
9 DecodeError,
10};
11
12const IFLA_MACSEC_SCI: u16 = 1;
13const IFLA_MACSEC_PORT: u16 = 2;
14const IFLA_MACSEC_ICV_LEN: u16 = 3;
15const IFLA_MACSEC_CIPHER_SUITE: u16 = 4;
16const IFLA_MACSEC_WINDOW: u16 = 5;
17const IFLA_MACSEC_ENCODING_SA: u16 = 6;
18const IFLA_MACSEC_ENCRYPT: u16 = 7;
19const IFLA_MACSEC_PROTECT: u16 = 8;
20const IFLA_MACSEC_INC_SCI: u16 = 9;
21const IFLA_MACSEC_ES: u16 = 10;
22const IFLA_MACSEC_SCB: u16 = 11;
23const IFLA_MACSEC_REPLAY_PROTECT: u16 = 12;
24const IFLA_MACSEC_VALIDATION: u16 = 13;
25const IFLA_MACSEC_OFFLOAD: u16 = 15;
27const MACSEC_VALIDATE_DISABLED: u8 = 0;
28const MACSEC_VALIDATE_CHECK: u8 = 1;
29const MACSEC_VALIDATE_STRICT: u8 = 2;
30const MACSEC_OFFLOAD_OFF: u8 = 0;
31const MACSEC_OFFLOAD_PHY: u8 = 1;
32const MACSEC_OFFLOAD_MAC: u8 = 2;
33const MACSEC_CIPHER_ID_GCM_AES_128: u64 = 0x0080C20001000001;
34const MACSEC_CIPHER_ID_GCM_AES_256: u64 = 0x0080C20001000002;
35const MACSEC_CIPHER_ID_GCM_AES_XPN_128: u64 = 0x0080C20001000003;
36const MACSEC_CIPHER_ID_GCM_AES_XPN_256: u64 = 0x0080C20001000004;
37const MACSEC_DEFAULT_CIPHER_ID: u64 = 0x0080020001000001;
38
39#[derive(Debug, PartialEq, Eq, Clone, Copy)]
40#[non_exhaustive]
41pub enum MacSecCipherId {
42 #[deprecated]
43 DefaultGcmAes128,
44 GcmAes128,
45 GcmAes256,
46 GcmAesXpn128,
47 GcmAesXpn256,
48 Other(u64),
49}
50
51impl From<u64> for MacSecCipherId {
52 fn from(d: u64) -> Self {
53 match d {
54 #[allow(deprecated)]
55 MACSEC_DEFAULT_CIPHER_ID => Self::DefaultGcmAes128,
56 MACSEC_CIPHER_ID_GCM_AES_128 => Self::GcmAes128,
57 MACSEC_CIPHER_ID_GCM_AES_256 => Self::GcmAes256,
58 MACSEC_CIPHER_ID_GCM_AES_XPN_128 => Self::GcmAesXpn128,
59 MACSEC_CIPHER_ID_GCM_AES_XPN_256 => Self::GcmAesXpn256,
60 _ => Self::Other(d),
61 }
62 }
63}
64
65impl From<MacSecCipherId> for u64 {
66 fn from(d: MacSecCipherId) -> Self {
67 match d {
68 #[allow(deprecated)]
69 MacSecCipherId::DefaultGcmAes128 => MACSEC_DEFAULT_CIPHER_ID,
70 MacSecCipherId::GcmAes128 => MACSEC_CIPHER_ID_GCM_AES_128,
71 MacSecCipherId::GcmAes256 => MACSEC_CIPHER_ID_GCM_AES_256,
72 MacSecCipherId::GcmAesXpn128 => MACSEC_CIPHER_ID_GCM_AES_XPN_128,
73 MacSecCipherId::GcmAesXpn256 => MACSEC_CIPHER_ID_GCM_AES_XPN_256,
74 MacSecCipherId::Other(value) => value,
75 }
76 }
77}
78
79#[derive(Debug, PartialEq, Eq, Clone, Copy)]
80#[non_exhaustive]
81pub enum MacSecValidate {
82 Disabled,
83 Check,
84 Strict,
85 Other(u8),
86}
87
88impl From<u8> for MacSecValidate {
89 fn from(d: u8) -> Self {
90 match d {
91 MACSEC_VALIDATE_DISABLED => Self::Disabled,
92 MACSEC_VALIDATE_CHECK => Self::Check,
93 MACSEC_VALIDATE_STRICT => Self::Strict,
94 _ => Self::Other(d),
95 }
96 }
97}
98
99impl From<MacSecValidate> for u8 {
100 fn from(d: MacSecValidate) -> Self {
101 match d {
102 MacSecValidate::Disabled => MACSEC_VALIDATE_DISABLED,
103 MacSecValidate::Check => MACSEC_VALIDATE_CHECK,
104 MacSecValidate::Strict => MACSEC_VALIDATE_STRICT,
105 MacSecValidate::Other(value) => value,
106 }
107 }
108}
109
110#[derive(Debug, PartialEq, Eq, Clone, Copy)]
111#[non_exhaustive]
112pub enum MacSecOffload {
113 Off,
114 Phy,
115 Mac,
116 Other(u8),
117}
118
119impl From<u8> for MacSecOffload {
120 fn from(d: u8) -> Self {
121 match d {
122 MACSEC_OFFLOAD_OFF => Self::Off,
123 MACSEC_OFFLOAD_PHY => Self::Phy,
124 MACSEC_OFFLOAD_MAC => Self::Mac,
125 _ => Self::Other(d),
126 }
127 }
128}
129
130impl From<MacSecOffload> for u8 {
131 fn from(d: MacSecOffload) -> Self {
132 match d {
133 MacSecOffload::Off => MACSEC_OFFLOAD_OFF,
134 MacSecOffload::Phy => MACSEC_OFFLOAD_PHY,
135 MacSecOffload::Mac => MACSEC_OFFLOAD_MAC,
136 MacSecOffload::Other(value) => value,
137 }
138 }
139}
140
141#[derive(Debug, PartialEq, Eq, Clone)]
142#[non_exhaustive]
143pub enum InfoMacSec {
144 Sci(u64),
145 Port(u16),
146 IcvLen(u8),
147 CipherSuite(MacSecCipherId),
148 Window(u32),
149 EncodingSa(u8),
150 Encrypt(u8),
151 Protect(u8),
152 IncSci(u8),
153 Es(u8),
154 Scb(u8),
155 ReplayProtect(u8),
156 Validation(MacSecValidate),
157 Offload(MacSecOffload),
158 Other(DefaultNla),
159}
160
161impl Nla for InfoMacSec {
162 fn value_len(&self) -> usize {
163 use self::InfoMacSec::*;
164 match self {
165 Sci(_) | CipherSuite(_) => 8,
166 Window(_) => 4,
167 Port(_) => 2,
168 IcvLen(_) | EncodingSa(_) | Encrypt(_) | Protect(_) | IncSci(_)
169 | Es(_) | Scb(_) | ReplayProtect(_) | Validation(_)
170 | Offload(_) => 1,
171 Other(nla) => nla.value_len(),
172 }
173 }
174
175 fn emit_value(&self, buffer: &mut [u8]) {
176 use self::InfoMacSec::*;
177 match self {
178 Sci(value) => NativeEndian::write_u64(buffer, *value),
179 CipherSuite(value) => {
180 NativeEndian::write_u64(buffer, (*value).into())
181 }
182 Window(value) => NativeEndian::write_u32(buffer, *value),
183 Port(value) => NativeEndian::write_u16(buffer, *value),
184 IcvLen(value) | EncodingSa(value) | Encrypt(value)
185 | Protect(value) | IncSci(value) | Es(value) | Scb(value)
186 | ReplayProtect(value) => buffer[0] = *value,
187 Offload(value) => buffer[0] = (*value).into(),
188 Validation(value) => buffer[0] = (*value).into(),
189 Other(nla) => nla.emit_value(buffer),
190 }
191 }
192
193 fn kind(&self) -> u16 {
194 use self::InfoMacSec::*;
195 match self {
196 Sci(_) => IFLA_MACSEC_SCI,
197 Port(_) => IFLA_MACSEC_PORT,
198 IcvLen(_) => IFLA_MACSEC_ICV_LEN,
199 CipherSuite(_) => IFLA_MACSEC_CIPHER_SUITE,
200 Window(_) => IFLA_MACSEC_WINDOW,
201 EncodingSa(_) => IFLA_MACSEC_ENCODING_SA,
202 Encrypt(_) => IFLA_MACSEC_ENCRYPT,
203 Protect(_) => IFLA_MACSEC_PROTECT,
204 IncSci(_) => IFLA_MACSEC_INC_SCI,
205 Es(_) => IFLA_MACSEC_ES,
206 Scb(_) => IFLA_MACSEC_SCB,
207 ReplayProtect(_) => IFLA_MACSEC_REPLAY_PROTECT,
208 Validation(_) => IFLA_MACSEC_VALIDATION,
209 Offload(_) => IFLA_MACSEC_OFFLOAD,
210 Other(nla) => nla.kind(),
211 }
212 }
213}
214
215impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoMacSec {
216 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
217 use self::InfoMacSec::*;
218 let payload = buf.value();
219 Ok(match buf.kind() {
220 IFLA_MACSEC_SCI => {
221 Sci(parse_u64(payload)
222 .context("invalid IFLA_MACSEC_SCI value")?)
223 }
224 IFLA_MACSEC_PORT => Port(
225 parse_u16(payload).context("invalid IFLA_MACSEC_PORT value")?,
226 ),
227 IFLA_MACSEC_ICV_LEN => IcvLen(
228 parse_u8(payload)
229 .context("invalid IFLA_MACSEC_ICV_LEN value")?,
230 ),
231 IFLA_MACSEC_CIPHER_SUITE => CipherSuite(
232 parse_u64(payload)
233 .context("invalid IFLA_MACSEC_CIPHER_SUITE value")?
234 .into(),
235 ),
236 IFLA_MACSEC_WINDOW => Window(
237 parse_u32(payload)
238 .context("invalid IFLA_MACSEC_WINDOW value")?,
239 ),
240 IFLA_MACSEC_ENCODING_SA => EncodingSa(
241 parse_u8(payload)
242 .context("invalid IFLA_MACSEC_ENCODING_SA value")?,
243 ),
244 IFLA_MACSEC_ENCRYPT => Encrypt(
245 parse_u8(payload)
246 .context("invalid IFLA_MACSEC_ENCRYPT value")?,
247 ),
248 IFLA_MACSEC_PROTECT => Protect(
249 parse_u8(payload)
250 .context("invalid IFLA_MACSEC_PROTECT value")?,
251 ),
252 IFLA_MACSEC_INC_SCI => IncSci(
253 parse_u8(payload)
254 .context("invalid IFLA_MACSEC_INC_SCI value")?,
255 ),
256 IFLA_MACSEC_ES => {
257 Es(parse_u8(payload).context("invalid IFLA_MACSEC_ES value")?)
258 }
259 IFLA_MACSEC_SCB => {
260 Scb(parse_u8(payload)
261 .context("invalid IFLA_MACSEC_SCB value")?)
262 }
263 IFLA_MACSEC_REPLAY_PROTECT => ReplayProtect(
264 parse_u8(payload)
265 .context("invalid IFLA_MACSEC_REPLAY_PROTECT value")?,
266 ),
267 IFLA_MACSEC_VALIDATION => Validation(
268 parse_u8(payload)
269 .context("invalid IFLA_MACSEC_VALIDATION value")?
270 .into(),
271 ),
272 IFLA_MACSEC_OFFLOAD => Offload(
273 parse_u8(payload)
274 .context("invalid IFLA_MACSEC_OFFLOAD value")?
275 .into(),
276 ),
277 kind => Other(
278 DefaultNla::parse(buf)
279 .context(format!("unknown NLA type {kind}"))?,
280 ),
281 })
282 }
283}