1use std::ffi::{CStr, CString};
2use std::mem;
3use std::str;
4
5use crate::core::hardware_address::HardwareAddress;
6use crate::core::message::netlink_padding;
7use crate::core::pack::{NativePack, NativeUnpack};
8use crate::errors::{NetlinkError, NetlinkErrorKind, Result};
9
10pub fn nested_attribute_array(data: &[u8]) -> Vec<Vec<Attribute>> {
22 let vs = mem::size_of::<u16>();
23 let mut attrs = vec![];
24 let mut d = &data[..];
25 while d.len() > (vs * 2) {
26 let size = u16::unpack(&d).unwrap();
27 let _index = u16::unpack(&d[vs..]).unwrap();
28 if d.len() > size as usize {
29 let (_, attributes) = Attribute::unpack_all(&d[(vs * 2)..size as usize]);
30 attrs.push(attributes);
31 } else {
32 break;
33 }
34 d = &d[size as usize..];
35 }
36 attrs
37}
38
39#[derive(Clone)]
49pub struct Attribute {
50 pub identifier: u16,
52 data: Vec<u8>,
54}
55
56impl Attribute {
57 const HEADER_SIZE: usize = 4;
58
59 pub fn unpack_all(data: &[u8]) -> (usize, Vec<Attribute>) {
61 let mut pos = 0usize;
62 let mut attrs = vec![];
63 loop {
64 match Attribute::unpack_with_size(&data[pos..]) {
65 Ok(r) => {
66 attrs.push(r.1);
67 pos += r.0;
68 }
69 Err(_) => {
70 break;
71 }
72 }
73 }
74 (pos, attrs)
75 }
76
77 pub fn new_bytes<ID: Into<u16>>(identifier: ID, value: &[u8]) -> Attribute {
79 Attribute {
80 identifier: identifier.into(),
81 data: value.to_vec(),
82 }
83 }
84
85 pub fn new_string_with_nul<ID: Into<u16>>(identifier: ID, value: &str) -> Attribute {
87 let c_string = CString::new(value).unwrap();
88 Attribute {
89 identifier: identifier.into(),
90 data: c_string.into_bytes_with_nul(),
91 }
92 }
93
94 pub fn new_string<ID: Into<u16>>(identifier: ID, value: &str) -> Attribute {
96 let string = CString::new(value).unwrap();
97 Attribute {
98 identifier: identifier.into(),
99 data: string.into_bytes(),
100 }
101 }
102
103 pub fn new<ID: Into<u16>, V: NativePack>(identifier: ID, value: V) -> Attribute {
105 let mut data = vec![0u8; mem::size_of::<V>()];
106 value.pack_unchecked(&mut data);
107 Attribute {
108 identifier: identifier.into(),
109 data: data,
110 }
111 }
112
113 pub fn len(&self) -> u16 {
115 self.data.len() as u16
116 }
117 pub fn total_len(&self) -> usize {
119 self.data.len() + Attribute::HEADER_SIZE
120 }
121 pub fn as_u8(&self) -> Result<u8> {
123 u8::unpack(&self.data)
124 }
125 pub fn as_u16(&self) -> Result<u16> {
127 u16::unpack(&self.data)
128 }
129 pub fn as_u32(&self) -> Result<u32> {
131 u32::unpack(&self.data)
132 }
133 pub fn as_u64(&self) -> Result<u64> {
135 u64::unpack(&self.data)
136 }
137 pub fn as_i8(&self) -> Result<i8> {
139 i8::unpack(&self.data)
140 }
141 pub fn as_i16(&self) -> Result<i16> {
143 i16::unpack(&self.data)
144 }
145 pub fn as_i32(&self) -> Result<i32> {
147 i32::unpack(&self.data)
148 }
149 pub fn as_i64(&self) -> Result<i64> {
151 i64::unpack(&self.data)
152 }
153 pub fn as_string(&self) -> Result<String> {
155 match CStr::from_bytes_with_nul(&self.data) {
156 Ok(bytes) => {
157 let s = bytes.to_str()?;
158 Ok(String::from(s))
159 }
160 Err(_) => {
161 let s = String::from_utf8(self.data.clone())?;
162 Ok(s)
163 }
164 }
165 }
166 pub fn as_hardware_address(&self) -> Result<HardwareAddress> {
168 HardwareAddress::unpack(&self.data)
169 }
170 pub fn as_bytes(&self) -> Vec<u8> {
172 self.data.clone()
173 }
174}
175
176impl NativePack for Attribute {
177 fn pack_size(&self) -> usize {
178 self.total_len()
179 }
180 fn pack<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8]> {
181 let length = self.total_len() as u16;
182 let slice = length.pack(buffer)?;
183 let slice = self.identifier.pack(slice)?;
184 let slice = self.data.pack(slice)?;
185 let padding = netlink_padding(self.data.len());
186 Ok(&mut slice[padding..])
187 }
188 fn pack_unchecked(&self, buffer: &mut [u8]) {
189 let length = self.total_len() as u16;
190 length.pack_unchecked(buffer);
191 self.identifier.pack_unchecked(&mut buffer[2..]);
192 self.data.pack_unchecked(&mut buffer[4..]);
193 }
194}
195
196impl NativeUnpack for Attribute {
197 fn unpack_with_size(buffer: &[u8]) -> Result<(usize, Self)> {
198 if buffer.len() < Attribute::HEADER_SIZE {
199 return Err(NetlinkError::new(NetlinkErrorKind::NotEnoughData).into());
200 }
201 let length = u16::unpack_unchecked(buffer) as usize;
202 let identifier = u16::unpack_unchecked(&buffer[2..]);
203
204 let padding = netlink_padding(length);
205 if buffer.len() < (length + padding) {
206 return Err(NetlinkError::new(NetlinkErrorKind::NotEnoughData).into());
207 }
208 let attr_data = (&buffer[4..length]).to_vec();
209 Ok((
210 length + padding,
211 Attribute {
212 identifier: identifier,
213 data: attr_data,
214 },
215 ))
216 }
217 fn unpack_unchecked(buffer: &[u8]) -> Self {
218 let length = u16::unpack_unchecked(buffer) as usize;
219 let identifier = u16::unpack_unchecked(&buffer[2..]);
220 let attr_data = (&buffer[4..length]).to_vec();
221 Attribute {
222 identifier: identifier,
223 data: attr_data,
224 }
225 }
226}
227
228#[cfg(test)]
229mod tests {
230 use super::*;
231
232 #[test]
233 fn unpack_attribute() {
234 let data = [
235 0x07, 0x00, 0x00, 0x10, 0x11, 0xaa, 0x55, 0xee, ];
240 let (used, attr) = Attribute::unpack_with_size(&data).unwrap();
241 assert_eq!(used, 8);
242 assert_eq!(attr.data.len(), 3usize);
243 assert_eq!(attr.identifier, 0x1000u16);
244 assert_eq!(attr.data[0], 0x11);
245 assert_eq!(attr.data[1], 0xaa);
246 assert_eq!(attr.data[2], 0x55);
247
248 let data = [
249 0x08, 0x00, 0x00, 0x10, 0x11, 0xaa, 0x55, 0xee, ];
253 let (used, attr) = Attribute::unpack_with_size(&data).unwrap();
254 assert_eq!(used, 8);
255 assert_eq!(attr.data.len(), 4usize);
256 assert_eq!(attr.identifier, 0x1000u16);
257 assert_eq!(attr.data[0], 0x11);
258 assert_eq!(attr.data[1], 0xaa);
259 assert_eq!(attr.data[2], 0x55);
260 assert_eq!(attr.data[3], 0xee);
261 }
262
263 #[test]
264 fn unpack_attributes() {
265 let data = [
266 0x07, 0x00, 0x00, 0x10, 0x11, 0xaa, 0x55, 0xee, 0x08, 0x00, 0x00, 0x10, 0x11, 0xaa, 0x55, 0xee, ];
274 let (used, attrs) = Attribute::unpack_all(&data);
275 assert_eq!(used, 16usize);
276 assert_eq!(attrs.len(), 2usize);
277
278 assert_eq!(attrs[0].data.len(), 3usize);
279 assert_eq!(attrs[0].identifier, 0x1000u16);
280 assert_eq!(attrs[0].data[0], 0x11);
281 assert_eq!(attrs[0].data[1], 0xaa);
282 assert_eq!(attrs[0].data[2], 0x55);
283
284 assert_eq!(attrs[1].data.len(), 4usize);
285 assert_eq!(attrs[1].identifier, 0x1000u16);
286 assert_eq!(attrs[1].data[0], 0x11);
287 assert_eq!(attrs[1].data[1], 0xaa);
288 assert_eq!(attrs[1].data[2], 0x55);
289 assert_eq!(attrs[1].data[3], 0xee);
290 }
291
292 #[test]
293 fn pack_attribute() {
294 let data = [
295 0x07, 0x00, 0x55, 0x81, 0x11, 0xaa, 0x55, 0x00, ];
300 let attr = Attribute {
301 identifier: 0x8155,
302 data: vec![0x11, 0xaa, 0x55],
303 };
304 let mut buffer = [0u8; 32];
305 {
306 let slice = attr.pack(&mut buffer).unwrap();
307 assert_eq!(slice.len(), 24);
308 }
309 assert_eq!(&buffer[0..8], data);
310 }
311}