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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// SPDX-License-Identifier: MIT
use std::os::unix::io::RawFd;
use futures::stream::StreamExt;
use netlink_packet_core::{
NetlinkMessage, NLM_F_ACK, NLM_F_CREATE, NLM_F_EXCL, NLM_F_REQUEST,
};
use netlink_packet_route::{
link::nlas::Nla, LinkMessage, RtnlMessage, IFF_NOARP, IFF_PROMISC, IFF_UP,
};
use crate::{try_nl, Error, Handle};
pub struct LinkSetRequest {
handle: Handle,
message: LinkMessage,
}
impl LinkSetRequest {
pub(crate) fn new(handle: Handle, index: u32) -> Self {
let mut message = LinkMessage::default();
message.header.index = index;
LinkSetRequest { handle, message }
}
/// Execute the request
pub async fn execute(self) -> Result<(), Error> {
let LinkSetRequest {
mut handle,
message,
} = self;
let mut req = NetlinkMessage::from(RtnlMessage::SetLink(message));
req.header.flags =
NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE;
let mut response = handle.request(req)?;
while let Some(message) = response.next().await {
try_nl!(message);
}
Ok(())
}
/// Return a mutable reference to the request
pub fn message_mut(&mut self) -> &mut LinkMessage {
&mut self.message
}
/// Attach the link to a bridge (its _master_). This is equivalent to `ip
/// link set LINK master BRIDGE`. To succeed, both the bridge and the
/// link that is being attached must be UP.
///
/// To Remove a link from a bridge, set its master to zero.
/// This is equvalent to `ip link set LINK nomaster`
pub fn master(mut self, master_index: u32) -> Self {
self.message.nlas.push(Nla::Master(master_index));
self
}
/// Detach the link from its _master_. This is equivalent to `ip link set
/// LINK nomaster`. To succeed, the link that is being detached must be
/// UP.
pub fn nomaster(mut self) -> Self {
self.message.nlas.push(Nla::Master(0u32));
self
}
/// Set the link with the given index up (equivalent to `ip link set dev DEV
/// up`)
pub fn up(mut self) -> Self {
self.message.header.flags |= IFF_UP;
self.message.header.change_mask |= IFF_UP;
self
}
/// Set the link with the given index down (equivalent to `ip link set dev
/// DEV down`)
pub fn down(mut self) -> Self {
self.message.header.flags &= !IFF_UP;
self.message.header.change_mask |= IFF_UP;
self
}
/// Enable or disable promiscious mode of the link with the given index
/// (equivalent to `ip link set dev DEV promisc on/off`)
pub fn promiscuous(mut self, enable: bool) -> Self {
if enable {
self.message.header.flags |= IFF_PROMISC;
} else {
self.message.header.flags &= !IFF_PROMISC;
}
self.message.header.change_mask |= IFF_PROMISC;
self
}
/// Enable or disable the ARP protocol of the link with the given index
/// (equivalent to `ip link set dev DEV arp on/off`)
pub fn arp(mut self, enable: bool) -> Self {
if enable {
self.message.header.flags &= !IFF_NOARP;
} else {
self.message.header.flags |= IFF_NOARP;
}
self.message.header.change_mask |= IFF_NOARP;
self
}
/// Set the name of the link with the given index (equivalent to `ip link
/// set DEV name NAME`)
pub fn name(mut self, name: String) -> Self {
self.message.nlas.push(Nla::IfName(name));
self
}
/// Set the mtu of the link with the given index (equivalent to `ip link set
/// DEV mtu MTU`)
pub fn mtu(mut self, mtu: u32) -> Self {
self.message.nlas.push(Nla::Mtu(mtu));
self
}
/// Set the hardware address of the link with the given index (equivalent to
/// `ip link set DEV address ADDRESS`)
pub fn address(mut self, address: Vec<u8>) -> Self {
self.message.nlas.push(Nla::Address(address));
self
}
/// Move this network device into the network namespace of the process with
/// the given `pid`.
pub fn setns_by_pid(mut self, pid: u32) -> Self {
self.message.nlas.push(Nla::NetNsPid(pid));
self
}
/// Move this network device into the network namespace corresponding to the
/// given file descriptor.
pub fn setns_by_fd(mut self, fd: RawFd) -> Self {
self.message.nlas.push(Nla::NetNsFd(fd));
self
}
}