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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// Copyright (C) 2018 - Will Glozer. All rights reserved.

use std::net::IpAddr;
use crate::Message;
use crate::api::RTA;
use crate::err::Invalid;
use crate::ffi::rtmsg;
use super::ip;

#[derive(Debug, Default)]
pub struct Route {
    pub kind:     u8,
    pub flags:    u32,
    pub scope:    u8,
    pub tos:      u8,
    pub table:    u8,
    pub protocol: u8,
    pub src:      Option<IpAddr>,
    pub dst:      Option<IpAddr>,
    pub iif:      u32,
    pub oif:      u32,
    pub gateway:  Option<IpAddr>,
}

pub fn route(msg: &Message<rtmsg>) -> Result<Route, Invalid> {
    let mut route = Route {
        kind:     msg.rtm_type,
        flags:    msg.rtm_flags,
        scope:    msg.rtm_scope,
        tos:      msg.rtm_tos,
        table:    msg.rtm_table,
        protocol: msg.rtm_protocol,
        ..Route::default()
    };

    let ip = |octets| ip(msg.rtm_family, octets);

    for attr in msg.attrs() {
        match attr? {
            RTA::Src(octets)     => route.src     = Some(ip(octets)?),
            RTA::Dst(octets)     => route.dst     = Some(ip(octets)?),
            RTA::IIF(iif)        => route.iif     = iif,
            RTA::OIF(oif)        => route.oif     = oif,
            RTA::Gateway(octets) => route.gateway = Some(ip(octets)?),
            _                    => (),
        }
    }

    Ok(route)
}