netlink_packet_route/address/
attribute.rs

1// SPDX-License-Identifier: MIT
2
3use crate::address::{AddressError, AddressFlags, CacheInfo, CacheInfoBuffer};
4use byteorder::{ByteOrder, NativeEndian};
5use netlink_packet_utils::nla::{DefaultNla, Nla, NlaBuffer};
6use netlink_packet_utils::parsers::{parse_string, parse_u32};
7use netlink_packet_utils::{Emitable, Parseable};
8use std::mem::size_of;
9use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
10
11const IFA_ADDRESS: u16 = 1;
12const IFA_LOCAL: u16 = 2;
13const IFA_LABEL: u16 = 3;
14const IFA_BROADCAST: u16 = 4;
15const IFA_ANYCAST: u16 = 5;
16const IFA_CACHEINFO: u16 = 6;
17const IFA_MULTICAST: u16 = 7;
18const IFA_FLAGS: u16 = 8;
19// TODO(Gris Ge)
20// const IFA_RT_PRIORITY: u16 = 9;
21// const IFA_TARGET_NETNSID: u16 = 10,
22// const IFA_PROTO: u16 = 11;
23
24// 32 bites
25const IPV4_ADDR_LEN: usize = 4;
26// 128 bites
27const IPV6_ADDR_LEN: usize = 16;
28
29#[derive(Debug, PartialEq, Eq, Clone)]
30#[non_exhaustive]
31pub enum AddressAttribute {
32    Address(IpAddr),
33    Local(IpAddr),
34    Label(String),
35    /// IPv4 only
36    Broadcast(Ipv4Addr),
37    /// IPv6 only
38    Anycast(Ipv6Addr),
39    CacheInfo(CacheInfo),
40    /// IPv6 only
41    Multicast(Ipv6Addr),
42    Flags(AddressFlags),
43    Other(DefaultNla),
44}
45
46impl Nla for AddressAttribute {
47    fn value_len(&self) -> usize {
48        match *self {
49            Self::Broadcast(_) => IPV4_ADDR_LEN,
50            Self::Anycast(_) | Self::Multicast(_) => IPV6_ADDR_LEN,
51            Self::Address(ref addr) | Self::Local(ref addr) => {
52                if addr.is_ipv6() {
53                    IPV6_ADDR_LEN
54                } else {
55                    IPV4_ADDR_LEN
56                }
57            }
58            Self::Label(ref string) => string.as_bytes().len() + 1,
59
60            Self::Flags(_) => size_of::<u32>(),
61
62            Self::CacheInfo(ref attr) => attr.buffer_len(),
63
64            Self::Other(ref attr) => attr.value_len(),
65        }
66    }
67
68    fn emit_value(&self, buffer: &mut [u8]) {
69        match *self {
70            Self::Broadcast(ref addr) => buffer.copy_from_slice(&addr.octets()),
71            Self::Anycast(ref addr) | Self::Multicast(ref addr) => {
72                buffer.copy_from_slice(&addr.octets())
73            }
74            Self::Address(ref addr) | Self::Local(ref addr) => match addr {
75                IpAddr::V4(addr4) => buffer.copy_from_slice(&addr4.octets()),
76                IpAddr::V6(addr6) => buffer.copy_from_slice(&addr6.octets()),
77            },
78            Self::Label(ref string) => {
79                buffer[..string.len()].copy_from_slice(string.as_bytes());
80                buffer[string.len()] = 0;
81            }
82            Self::Flags(ref value) => NativeEndian::write_u32(buffer, value.bits()),
83            Self::CacheInfo(ref attr) => attr.emit(buffer),
84            Self::Other(ref attr) => attr.emit_value(buffer),
85        }
86    }
87
88    fn kind(&self) -> u16 {
89        match *self {
90            Self::Address(_) => IFA_ADDRESS,
91            Self::Local(_) => IFA_LOCAL,
92            Self::Label(_) => IFA_LABEL,
93            Self::Broadcast(_) => IFA_BROADCAST,
94            Self::Anycast(_) => IFA_ANYCAST,
95            Self::CacheInfo(_) => IFA_CACHEINFO,
96            Self::Multicast(_) => IFA_MULTICAST,
97            Self::Flags(_) => IFA_FLAGS,
98            Self::Other(ref nla) => nla.kind(),
99        }
100    }
101}
102
103impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for AddressAttribute {
104    type Error = AddressError;
105
106    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, AddressError> {
107        let payload = buf.value();
108        Ok(match buf.kind() {
109            IFA_ADDRESS => {
110                if payload.len() == IPV4_ADDR_LEN {
111                    let mut data = [0u8; IPV4_ADDR_LEN];
112                    data.copy_from_slice(&payload[0..IPV4_ADDR_LEN]);
113                    Self::Address(IpAddr::from(data))
114                } else if payload.len() == IPV6_ADDR_LEN {
115                    let mut data = [0u8; IPV6_ADDR_LEN];
116                    data.copy_from_slice(&payload[0..IPV6_ADDR_LEN]);
117                    Self::Address(IpAddr::from(data))
118                } else {
119                    return Err(AddressError::ParseAttributeInvalidPayload {
120                        kind: "IFA_ADDRESS",
121                        payload_length: payload.len(),
122                    });
123                }
124            }
125            IFA_LOCAL => {
126                if payload.len() == IPV4_ADDR_LEN {
127                    let mut data = [0u8; IPV4_ADDR_LEN];
128                    data.copy_from_slice(&payload[0..IPV4_ADDR_LEN]);
129                    Self::Local(IpAddr::from(data))
130                } else if payload.len() == IPV6_ADDR_LEN {
131                    let mut data = [0u8; IPV6_ADDR_LEN];
132                    data.copy_from_slice(&payload[0..IPV6_ADDR_LEN]);
133                    Self::Local(IpAddr::from(data))
134                } else {
135                    return Err(AddressError::ParseAttributeInvalidPayload {
136                        kind: "IFA_LOCAL",
137                        payload_length: payload.len(),
138                    });
139                }
140            }
141            IFA_LABEL => Self::Label(
142                parse_string(payload)
143                    .map_err(|err| AddressError::ParseAttribute { kind: "IFA_LABEL", err })?,
144            ),
145            IFA_BROADCAST => {
146                if payload.len() == IPV4_ADDR_LEN {
147                    let mut data = [0u8; IPV4_ADDR_LEN];
148                    data.copy_from_slice(&payload[0..IPV4_ADDR_LEN]);
149                    Self::Broadcast(Ipv4Addr::from(data))
150                } else {
151                    return Err(AddressError::ParseAttributeInvalidPayload {
152                        kind: "IFA_BROADCAST",
153                        payload_length: payload.len(),
154                    });
155                }
156            }
157            IFA_ANYCAST => {
158                if payload.len() == IPV6_ADDR_LEN {
159                    let mut data = [0u8; IPV6_ADDR_LEN];
160                    data.copy_from_slice(&payload[0..IPV6_ADDR_LEN]);
161                    Self::Anycast(Ipv6Addr::from(data))
162                } else {
163                    return Err(AddressError::ParseAttributeInvalidPayload {
164                        kind: "IFA_ANYCAST",
165                        payload_length: payload.len(),
166                    });
167                }
168            }
169            IFA_CACHEINFO => Self::CacheInfo(
170                CacheInfo::parse(&CacheInfoBuffer::new(payload))
171                    .map_err(|err| AddressError::ParseAttribute { kind: "IFA_CACHEINFO", err })?,
172            ),
173            IFA_MULTICAST => {
174                if payload.len() == IPV6_ADDR_LEN {
175                    let mut data = [0u8; IPV6_ADDR_LEN];
176                    data.copy_from_slice(&payload[0..IPV6_ADDR_LEN]);
177                    Self::Multicast(Ipv6Addr::from(data))
178                } else {
179                    return Err(AddressError::ParseAttributeInvalidPayload {
180                        kind: "IFA_MULTICAST",
181                        payload_length: payload.len(),
182                    });
183                }
184            }
185            IFA_FLAGS => Self::Flags(AddressFlags::from_bits_retain(
186                parse_u32(payload)
187                    .map_err(|err| AddressError::ParseAttribute { kind: "IFA_FLAGS", err })?,
188            )),
189            kind => Self::Other(
190                DefaultNla::parse(buf)
191                    .map_err(|err| AddressError::ParseUnknownNLA { kind, err })?,
192            ),
193        })
194    }
195}