rtnetlink/link/
set.rs

1// SPDX-License-Identifier: MIT
2
3use crate::{
4    packet::{
5        nlas::link::Nla,
6        LinkMessage,
7        NetlinkMessage,
8        RtnlMessage,
9        IFF_NOARP,
10        IFF_PROMISC,
11        IFF_UP,
12        NLM_F_ACK,
13        NLM_F_CREATE,
14        NLM_F_EXCL,
15        NLM_F_REQUEST,
16    },
17    try_nl,
18    Error,
19    Handle,
20};
21use futures::stream::StreamExt;
22use std::os::unix::io::RawFd;
23
24pub struct LinkSetRequest {
25    handle: Handle,
26    message: LinkMessage,
27}
28
29impl LinkSetRequest {
30    pub(crate) fn new(handle: Handle, index: u32) -> Self {
31        let mut message = LinkMessage::default();
32        message.header.index = index;
33        LinkSetRequest { handle, message }
34    }
35
36    /// Execute the request
37    pub async fn execute(self) -> Result<(), Error> {
38        let LinkSetRequest {
39            mut handle,
40            message,
41        } = self;
42        let mut req = NetlinkMessage::from(RtnlMessage::SetLink(message));
43        req.header.flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE;
44
45        let mut response = handle.request(req)?;
46        while let Some(message) = response.next().await {
47            try_nl!(message);
48        }
49        Ok(())
50    }
51
52    /// Return a mutable reference to the request
53    pub fn message_mut(&mut self) -> &mut LinkMessage {
54        &mut self.message
55    }
56
57    /// Attach the link to a bridge (its _master_). This is equivalent to `ip link set LINK master
58    /// BRIDGE`. To succeed, both the bridge and the link that is being attached must be UP.
59    ///
60    /// To Remove a link from a bridge, set its master to zero.
61    /// This is equvalent to `ip link set LINK nomaster`
62    pub fn master(mut self, master_index: u32) -> Self {
63        self.message.nlas.push(Nla::Master(master_index));
64        self
65    }
66
67    /// Detach the link from its _master_. This is equivalent to `ip link set LINK nomaster`.
68    ///To succeed, the link that is being detached must be UP.
69    pub fn nomaster(mut self) -> Self {
70        self.message.nlas.push(Nla::Master(0u32));
71        self
72    }
73
74    /// Set the link with the given index up (equivalent to `ip link set dev DEV up`)
75    pub fn up(mut self) -> Self {
76        self.message.header.flags |= IFF_UP;
77        self.message.header.change_mask |= IFF_UP;
78        self
79    }
80
81    /// Set the link with the given index down (equivalent to `ip link set dev DEV down`)
82    pub fn down(mut self) -> Self {
83        self.message.header.flags &= !IFF_UP;
84        self.message.header.change_mask |= IFF_UP;
85        self
86    }
87
88    /// Enable or disable promiscious mode of the link with the given index (equivalent to `ip link set dev DEV promisc on/off`)
89    pub fn promiscuous(mut self, enable: bool) -> Self {
90        if enable {
91            self.message.header.flags |= IFF_PROMISC;
92        } else {
93            self.message.header.flags &= !IFF_PROMISC;
94        }
95        self.message.header.change_mask |= IFF_PROMISC;
96        self
97    }
98
99    /// Enable or disable the ARP protocol of the link with the given index (equivalent to `ip link set dev DEV arp on/off`)
100    pub fn arp(mut self, enable: bool) -> Self {
101        if enable {
102            self.message.header.flags &= !IFF_NOARP;
103        } else {
104            self.message.header.flags |= IFF_NOARP;
105        }
106        self.message.header.change_mask |= IFF_NOARP;
107        self
108    }
109
110    /// Set the name of the link with the given index (equivalent to `ip link set DEV name NAME`)
111    pub fn name(mut self, name: String) -> Self {
112        self.message.nlas.push(Nla::IfName(name));
113        self
114    }
115
116    /// Set the mtu of the link with the given index (equivalent to `ip link set DEV mtu MTU`)
117    pub fn mtu(mut self, mtu: u32) -> Self {
118        self.message.nlas.push(Nla::Mtu(mtu));
119        self
120    }
121
122    /// Set the hardware address of the link with the given index (equivalent to `ip link set DEV address ADDRESS`)
123    pub fn address(mut self, address: Vec<u8>) -> Self {
124        self.message.nlas.push(Nla::Address(address));
125        self
126    }
127
128    /// Move this network device into the network namespace of the process with the given `pid`.
129    pub fn setns_by_pid(mut self, pid: u32) -> Self {
130        self.message.nlas.push(Nla::NetNsPid(pid));
131        self
132    }
133
134    /// Move this network device into the network namespace corresponding to the given file
135    /// descriptor.
136    pub fn setns_by_fd(mut self, fd: RawFd) -> Self {
137        self.message.nlas.push(Nla::NetNsFd(fd));
138        self
139    }
140}