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