netlink_packet_route/address/
attribute.rs
1use 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;
19const IPV4_ADDR_LEN: usize = 4;
26const 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 Broadcast(Ipv4Addr),
37 Anycast(Ipv6Addr),
39 CacheInfo(CacheInfo),
40 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}