rtnetlink/link/
set.rs

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