1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Copyright (C) 2020 - Will Glozer. All rights reserved.

use errno::Errno;
use crate::{Error, Netlink, Result};
use crate::ffi::*;
use super::{Bytes, Cursor, Message};

pub fn next<'a, T: Bytes>(c: &mut Cursor<'a>) -> Option<Result<Netlink<Message<'a, T>>>> {
    let (head, tail) = c.next::<nlmsghdr>()?;
    Some(match head.nlmsg_type {
        NLMSG_NOOP    => Ok(Netlink::Noop),
        NLMSG_OVERRUN => Ok(Netlink::Overrun),
        NLMSG_ERROR   => error(tail)?,
        _             => Ok(message(head, tail)?),
    })
}

fn message<T: Bytes>(head: nlmsghdr, mut tail: Cursor<'_>) -> Option<Netlink<Message<'_, T>>> {
    let done = head.nlmsg_type == NLMSG_DONE;
    match tail.next().map(|(data, tail)| Message::with(head, data, tail)) {
        Some(msg)    => Some(Netlink::Msg(msg)),
        None if done => Some(Netlink::Done),
        None         => None,
    }
}

fn error<T: Bytes>(mut tail: Cursor<'_>) -> Option<Result<Netlink<Message<'_, T>>>> {
    tail.next::<nlmsgerr>().and_then(|(err, _)| {
        Some(match err.error.checked_neg()? {
            0 => Ok(Netlink::Ack),
            n => Err(Error::Netlink(Errno(n))),
        })
    })
}