Skip to main content

netlink_packet_generic/
header.rs

1// SPDX-License-Identifier: MIT
2
3//! header definition of generic netlink packet
4use crate::constants::GENL_HDRLEN;
5use netlink_packet_core::{DecodeError, Emitable};
6use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
7
8/// Generic Netlink header
9#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10pub struct GenlHeader {
11    pub cmd: u8,
12    pub version: u8,
13}
14
15#[derive(
16    Debug,
17    PartialEq,
18    Eq,
19    Clone,
20    FromBytes,
21    IntoBytes,
22    KnownLayout,
23    Immutable,
24    Unaligned,
25)]
26#[repr(C, packed)]
27pub(crate) struct GenlHeaderBuffer {
28    cmd: u8,
29    version: u8,
30    reserved: u16,
31}
32
33impl Emitable for GenlHeader {
34    fn buffer_len(&self) -> usize {
35        GENL_HDRLEN
36    }
37
38    fn emit(&self, buffer: &mut [u8]) {
39        let raw = GenlHeaderBuffer::from(self);
40        buffer[..GENL_HDRLEN].copy_from_slice(raw.as_bytes());
41    }
42}
43
44impl GenlHeader {
45    pub fn parse(payload: &[u8]) -> Result<Self, DecodeError> {
46        let (raw, _) =
47            GenlHeaderBuffer::ref_from_prefix(payload).map_err(|_| {
48                DecodeError::buffer_too_small(payload.len(), GENL_HDRLEN)
49            })?;
50        Ok(Self {
51            cmd: raw.cmd,
52            version: raw.version,
53        })
54    }
55}
56
57impl From<&GenlHeader> for GenlHeaderBuffer {
58    fn from(header: &GenlHeader) -> Self {
59        Self {
60            cmd: header.cmd,
61            version: header.version,
62            // The kernel expects the reserved field to always be zero.
63            reserved: 0,
64        }
65    }
66}