File: get_links.rs

package info (click to toggle)
rust-rtnetlink 0.14.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 828 kB
  • sloc: makefile: 2
file content (117 lines) | stat: -rw-r--r-- 3,606 bytes parent folder | download | duplicates (2)
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// SPDX-License-Identifier: MIT
#![cfg(feature = "tokio_socket")]

use futures::stream::TryStreamExt;
use netlink_packet_route::{
    link::{LinkAttribute, LinkExtentMask},
    AddressFamily,
};
use rtnetlink::{new_connection, Error, Handle};

#[cfg(target_os = "freebsd")]
fn main() -> () {}

#[cfg(not(target_os = "freebsd"))]
#[tokio::main]
async fn main() -> Result<(), ()> {
    env_logger::init();
    let (connection, handle, _) = new_connection().unwrap();
    tokio::spawn(connection);

    // Fetch a link by its index
    let index = 1;
    println!("*** retrieving link with index {index} ***");
    if let Err(e) = get_link_by_index(handle.clone(), index).await {
        eprintln!("{e}");
    }

    // Fetch a link by its name
    let name = "lo";
    println!("*** retrieving link named \"{name}\" ***");
    if let Err(e) = get_link_by_name(handle.clone(), name.to_string()).await {
        eprintln!("{e}");
    }

    // Dump all the links and print their index and name
    println!("*** dumping links ***");
    if let Err(e) = dump_links(handle.clone()).await {
        eprintln!("{e}");
    }

    // Dump all the bridge vlan information
    if let Err(e) = dump_bridge_filter_info(handle.clone()).await {
        eprintln!("{e}");
    }

    Ok(())
}

async fn get_link_by_index(handle: Handle, index: u32) -> Result<(), Error> {
    let mut links = handle.link().get().match_index(index).execute();
    let msg = if let Some(msg) = links.try_next().await? {
        msg
    } else {
        eprintln!("no link with index {index} found");
        return Ok(());
    };
    // We should have received only one message
    assert!(links.try_next().await?.is_none());

    for nla in msg.attributes.into_iter() {
        if let LinkAttribute::IfName(name) = nla {
            println!("found link with index {index} (name = {name})");
            return Ok(());
        }
    }
    eprintln!(
        "found link with index {index}, but this link does not have a name"
    );
    Ok(())
}

async fn get_link_by_name(handle: Handle, name: String) -> Result<(), Error> {
    let mut links = handle.link().get().match_name(name.clone()).execute();
    if (links.try_next().await?).is_some() {
        println!("found link {name}");
        // We should only have one link with that name
        assert!(links.try_next().await?.is_none());
    } else {
        println!("no link link {name} found");
    }
    Ok(())
}

async fn dump_links(handle: Handle) -> Result<(), Error> {
    let mut links = handle.link().get().execute();
    'outer: while let Some(msg) = links.try_next().await? {
        for nla in msg.attributes.into_iter() {
            if let LinkAttribute::IfName(name) = nla {
                println!("found link {} ({})", msg.header.index, name);
                continue 'outer;
            }
        }
        eprintln!("found link {}, but the link has no name", msg.header.index);
    }
    Ok(())
}

#[cfg(not(target_os = "freebsd"))]
async fn dump_bridge_filter_info(handle: Handle) -> Result<(), Error> {
    let mut links = handle
        .link()
        .get()
        .set_filter_mask(AddressFamily::Bridge, vec![LinkExtentMask::Brvlan])
        .execute();
    'outer: while let Some(msg) = links.try_next().await? {
        for nla in msg.attributes.into_iter() {
            if let LinkAttribute::AfSpecBridge(data) = nla {
                println!(
                    "found interface {} with AfSpecBridge data {:?})",
                    msg.header.index, data
                );
                continue 'outer;
            }
        }
    }
    Ok(())
}