diff --git a/aya/src/sys/netlink.rs b/aya/src/sys/netlink.rs index 7b54fd73..cc5e5b4d 100644 --- a/aya/src/sys/netlink.rs +++ b/aya/src/sys/netlink.rs @@ -477,27 +477,16 @@ impl<'a> NestedAttrs<'a> { } } - fn write_attr(&mut self, attr_type: u16, value: T) -> io::Result<()> { - let attr = nlattr { - nla_type: attr_type as u16, - nla_len: (NLA_HDR_LEN + mem::size_of::()) as u16, - }; - - self.write_header(attr)?; - self.write_value(value)?; - - Ok(()) - } - - fn write_header(&mut self, value: T) -> Result<(), io::Error> { - write(self.buf, self.offset, value)?; - self.offset += NLA_HDR_LEN; - Ok(()) + fn write_attr(&mut self, attr_type: u16, value: T) -> Result { + let size = write_attr(&mut self.buf, self.offset, attr_type, value)?; + self.offset += size; + Ok(size) } - fn write_value(&mut self, value: T) -> Result<(), io::Error> { - self.offset += write(self.buf, self.offset, value)?; - Ok(()) + fn write_attr_bytes(&mut self, attr_type: u16, value: &[u8]) -> Result { + let size = write_attr_bytes(&mut self.buf, self.offset, attr_type, value)?; + self.offset += size; + Ok(size) } fn finish(self) -> Result { @@ -507,19 +496,55 @@ impl<'a> NestedAttrs<'a> { nla_len: nla_len as u16, }; - write(self.buf, 0, attr)?; + write_attr_header(self.buf, 0, attr)?; Ok(nla_len) } } -fn write(buf: &mut [u8], offset: usize, value: T) -> Result { - let value_size = mem::size_of::(); - if offset + value_size > buf.len() { - return Err(io::Error::new(io::ErrorKind::Other, "not space left")); +fn write_attr( + buf: &mut [u8], + offset: usize, + attr_type: u16, + value: T, +) -> Result { + let value = + unsafe { slice::from_raw_parts(&value as *const _ as *const _, mem::size_of::()) }; + write_attr_bytes(buf, offset, attr_type, value) +} + +fn write_attr_bytes( + buf: &mut [u8], + offset: usize, + attr_type: u16, + value: &[u8], +) -> Result { + let attr = nlattr { + nla_type: attr_type as u16, + nla_len: ((NLA_HDR_LEN + value.len()) as u16), + }; + + write_attr_header(buf, offset, attr)?; + let value_len = write_bytes(buf, offset + NLA_HDR_LEN, value)?; + + Ok(NLA_HDR_LEN + value_len) +} + +fn write_attr_header(buf: &mut [u8], offset: usize, attr: nlattr) -> Result { + let attr = + unsafe { slice::from_raw_parts(&attr as *const _ as *const _, mem::size_of::()) }; + + write_bytes(buf, offset, attr)?; + Ok(NLA_HDR_LEN) +} + +fn write_bytes(buf: &mut [u8], offset: usize, value: &[u8]) -> Result { + if offset + value.len() > buf.len() { + return Err(io::Error::new(io::ErrorKind::Other, "no space left")); } - unsafe { ptr::write_unaligned(buf[offset..].as_mut_ptr() as *mut T, value) }; - Ok(value_size) + buf[offset..offset + value.len()].copy_from_slice(value); + + Ok(value.len()) } #[cfg(test)]