rtnetlink/link/
builder.rs1use std::{marker::PhantomData, os::fd::RawFd};
4
5use crate::packet_route::{
6 link::{
7 InfoData, InfoKind, InfoPortData, InfoPortKind, LinkAttribute,
8 LinkFlags, LinkHeader, LinkInfo, LinkMessage,
9 },
10 AddressFamily,
11};
12
13#[derive(Debug)]
39pub struct LinkUnspec;
40
41impl LinkUnspec {
42 pub fn new_with_index(index: u32) -> LinkMessageBuilder<Self> {
44 LinkMessageBuilder::<LinkUnspec>::default().index(index)
45 }
46
47 pub fn new_with_name(name: &str) -> LinkMessageBuilder<Self> {
49 LinkMessageBuilder::<LinkUnspec>::default().name(name.to_string())
50 }
51}
52
53#[derive(Debug)]
54pub struct LinkMessageBuilder<T> {
58 pub(crate) header: LinkHeader,
59 pub(crate) info_kind: Option<InfoKind>,
60 pub(crate) info_data: Option<InfoData>,
61 pub(crate) port_kind: Option<InfoPortKind>,
62 pub(crate) port_data: Option<InfoPortData>,
63 pub(crate) extra_attriutes: Vec<LinkAttribute>,
64 _phantom: PhantomData<T>,
65}
66
67impl<T> Default for LinkMessageBuilder<T> {
68 fn default() -> Self {
69 Self {
70 header: Default::default(),
71 info_kind: None,
72 info_data: Default::default(),
73 extra_attriutes: Default::default(),
74 port_kind: None,
75 port_data: None,
76 _phantom: Default::default(),
77 }
78 }
79}
80
81impl<T> LinkMessageBuilder<T> {
82 pub fn new_with_info_kind(info_kind: InfoKind) -> Self {
83 Self {
84 info_kind: Some(info_kind),
85 ..Default::default()
86 }
87 }
88
89 pub fn set_header(self, header: LinkHeader) -> Self {
91 let mut ret = self;
92 ret.header = header;
93 ret
94 }
95
96 pub fn append_extra_attribute(self, link_attr: LinkAttribute) -> Self {
98 let mut ret = self;
99 ret.extra_attriutes.push(link_attr);
100 ret
101 }
102
103 pub fn set_info_data(self, info_data: InfoData) -> Self {
105 let mut ret = self;
106 ret.info_data = Some(info_data);
107 ret
108 }
109
110 pub fn up(self) -> Self {
112 let mut ret = self;
113 ret.header.flags |= LinkFlags::Up;
114 ret.header.change_mask |= LinkFlags::Up;
115 ret
116 }
117
118 pub fn down(self) -> Self {
120 let mut ret = self;
121 ret.header.flags.remove(LinkFlags::Up);
122 ret.header.change_mask |= LinkFlags::Up;
123 ret
124 }
125
126 pub fn promiscuous(self, enable: bool) -> Self {
129 let mut ret = self;
130 if enable {
131 ret.header.flags |= LinkFlags::Promisc;
132 } else {
133 ret.header.flags.remove(LinkFlags::Promisc);
134 }
135 ret.header.change_mask |= LinkFlags::Promisc;
136 ret
137 }
138
139 pub fn arp(self, enable: bool) -> Self {
142 let mut ret = self;
143 if enable {
144 ret.header.flags.remove(LinkFlags::Noarp);
145 } else {
146 ret.header.flags |= LinkFlags::Noarp;
147 }
148 ret.header.change_mask |= LinkFlags::Noarp;
149 ret
150 }
151
152 pub fn name(self, name: String) -> Self {
153 self.append_extra_attribute(LinkAttribute::IfName(name))
154 }
155
156 pub fn mtu(self, mtu: u32) -> Self {
159 self.append_extra_attribute(LinkAttribute::Mtu(mtu))
160 }
161
162 pub fn index(self, index: u32) -> Self {
165 let mut ret = self;
166 ret.header.index = index;
167 ret
168 }
169
170 pub fn interface_family(self, family: AddressFamily) -> Self {
171 let mut ret = self;
172 ret.header.interface_family = family;
173 ret
174 }
175
176 pub fn address(self, address: Vec<u8>) -> Self {
179 self.append_extra_attribute(LinkAttribute::Address(address))
180 }
181
182 pub fn setns_by_pid(self, pid: u32) -> Self {
185 self.append_extra_attribute(LinkAttribute::NetNsPid(pid))
186 }
187
188 pub fn setns_by_fd(self, fd: RawFd) -> Self {
191 self.append_extra_attribute(LinkAttribute::NetNsFd(fd))
192 }
193
194 pub fn link(self, index: u32) -> Self {
197 self.append_extra_attribute(LinkAttribute::Link(index))
198 }
199
200 pub fn controller(self, ctrl_index: u32) -> Self {
203 self.append_extra_attribute(LinkAttribute::Controller(ctrl_index))
204 }
205
206 pub fn nocontroller(self) -> Self {
210 self.append_extra_attribute(LinkAttribute::Controller(0))
211 }
212
213 pub fn set_port_kind(self, port_kind: InfoPortKind) -> Self {
214 let mut ret = self;
215 ret.port_kind = Some(port_kind);
216 ret
217 }
218
219 pub fn set_port_data(self, port_data: InfoPortData) -> Self {
222 let mut ret = self;
223 ret.port_data = Some(port_data);
224 ret
225 }
226
227 pub fn build(self) -> LinkMessage {
228 let mut message = LinkMessage::default();
229 message.header = self.header;
230
231 if !self.extra_attriutes.is_empty() {
232 message.attributes = self.extra_attriutes;
233 }
234
235 let mut link_infos: Vec<LinkInfo> = Vec::new();
236 if let Some(info_kind) = self.info_kind {
237 link_infos.push(LinkInfo::Kind(info_kind));
238 }
239 if let Some(info_data) = self.info_data {
240 link_infos.push(LinkInfo::Data(info_data));
241 }
242
243 if let Some(port_kind) = self.port_kind {
244 link_infos.push(LinkInfo::PortKind(port_kind));
245 }
246
247 if let Some(port_data) = self.port_data {
248 link_infos.push(LinkInfo::PortData(port_data));
249 }
250
251 if !link_infos.is_empty() {
252 message.attributes.push(LinkAttribute::LinkInfo(link_infos));
253 }
254
255 message
256 }
257}
258
259impl LinkMessageBuilder<LinkUnspec> {
260 pub fn new() -> Self {
261 Self::default()
262 }
263}