netlink_packet_route/link/link_info/gre/
info_gre6.rs

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