netlink_packet_route/link/link_info/
macsec.rs

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