Skip to content

Commit 4a6b4a5

Browse files
committed
fix iproute2 guard
1 parent e8bd448 commit 4a6b4a5

File tree

2 files changed

+51
-30
lines changed

2 files changed

+51
-30
lines changed

src/guards.rs

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -212,13 +212,19 @@ pub struct IpRuleGuard {
212212

213213
impl IpRuleGuard {
214214
pub fn new(fwmark: u32, table: u32, ip_stack: IPStack) -> Self {
215-
fn update_local_ip_table(ip_cmd: IPRoute2, action: Action, table: &str, ip_stack: IPStack) {
216-
let local_ip = match ip_stack {
217-
IPStack::V4 => "0.0.0.0/0",
218-
IPStack::V6 => "::/0",
219-
_ => unreachable!(),
220-
};
215+
let ipv4_cmd = IPRoute2Builder::new().cmd_uid(0).cmd_gid(0).build();
216+
let ipv6_cmd = IPRoute2Builder::new().ipv6().cmd_uid(0).cmd_gid(0).build();
221217

218+
fn update_fwmark(ip_cmd: &IPRoute2, action: Action, fwmark: &str, table: &str) {
219+
ip_cmd
220+
.object(Object::rule)
221+
.action(action)
222+
.run(["fwmark", fwmark, "table", table])
223+
.expect("ip {action} rule failed");
224+
}
225+
226+
fn update_local_ip_table(ip_cmd: &IPRoute2, action: Action, table: &str) {
227+
let local_ip = if ip_cmd.ipv6 { "::/0" } else { "0.0.0.0/0" };
222228
ip_cmd
223229
.object(Object::route)
224230
.action(action)
@@ -230,21 +236,17 @@ impl IpRuleGuard {
230236
let thread = std::thread::spawn(move || {
231237
let fwmark = fwmark.to_string();
232238
let table = table.to_string();
233-
let ip_cmd = IPRoute2Builder::new().cmd_uid(0).cmd_gid(0).build();
234-
ip_cmd
235-
.object(Object::rule)
236-
.add()
237-
.run(["fwmark", &fwmark, "table", &table])
238-
.expect("ip add rule failed");
239239
if ip_stack.has_v4() {
240-
update_local_ip_table(ip_cmd, Action::Add, &table, IPStack::V4);
240+
update_fwmark(&ipv4_cmd, Action::Add, &fwmark, &table);
241+
update_local_ip_table(&ipv4_cmd, Action::Add, &table);
241242
}
242243
if ip_stack.has_v6() {
243-
update_local_ip_table(ip_cmd, Action::Add, &table, IPStack::V6);
244+
update_fwmark(&ipv6_cmd, Action::Add, &fwmark, &table);
245+
update_local_ip_table(&ipv6_cmd, Action::Add, &table);
244246
}
245247

246248
loop {
247-
if ip_cmd
249+
if ipv4_cmd
248250
.object(Object::rule)
249251
.list()
250252
.run(["fwmark", &fwmark])
@@ -255,11 +257,12 @@ impl IpRuleGuard {
255257
tracing::warn!(
256258
"detected disappearing routing policy, possibly due to interruped network, resetting"
257259
);
258-
ip_cmd
259-
.object(Object::rule)
260-
.add()
261-
.run(["fwmark", &fwmark, "table", &table])
262-
.expect("ip add routing rules failed");
260+
if ip_stack.has_v4() {
261+
update_fwmark(&ipv4_cmd, Action::Add, &fwmark, &table);
262+
}
263+
if ip_stack.has_v6() {
264+
update_fwmark(&ipv6_cmd, Action::Add, &fwmark, &table);
265+
}
263266
}
264267
if receiver.recv_timeout(Duration::from_secs(1)).is_ok() {
265268
break;
@@ -278,17 +281,15 @@ impl IpRuleGuard {
278281
x.guard_thread.join().unwrap();
279282
let mark = x.fwmark.to_string();
280283
let table = x.table.to_string();
281-
let ip_cmd = IPRoute2Builder::new().cmd_uid(0).cmd_gid(0).build();
282-
ip_cmd
283-
.object(Object::rule)
284-
.delete()
285-
.run(["fwmark", &mark, "table", &table])
286-
.expect("ip drop routing rules failed");
287284
if x.ip_stack.has_v4() {
288-
update_local_ip_table(ip_cmd, Action::Delete, &table, IPStack::V4);
285+
let ipv4_cmd = IPRoute2Builder::new().cmd_uid(0).cmd_gid(0).build();
286+
update_fwmark(&ipv4_cmd, Action::Delete, &mark, &table);
287+
update_local_ip_table(&ipv4_cmd, Action::Delete, &table);
289288
}
290289
if x.ip_stack.has_v6() {
291-
update_local_ip_table(ip_cmd, Action::Delete, &table, IPStack::V6);
290+
let ipv6_cmd = IPRoute2Builder::new().ipv6().cmd_uid(0).cmd_gid(0).build();
291+
update_fwmark(&ipv6_cmd, Action::Delete, &mark, &table);
292+
update_local_ip_table(&ipv6_cmd, Action::Delete, &table);
292293
}
293294
});
294295
Self {

src/iproute2.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ pub type Result<T, E = IPRoute2Error> = core::result::Result<T, E>;
1414

1515
#[derive(Debug, Clone, Copy)]
1616
pub struct IPRoute2 {
17-
binary: &'static str,
17+
pub binary: &'static str,
18+
pub ipv6: bool,
1819
object: Option<Object>,
1920
action: Option<Action>,
2021
cmd_uid: Option<u32>,
@@ -80,6 +81,7 @@ impl Action {
8081
#[derive(Debug, Default, Clone)]
8182
pub struct IPRoute2Builder {
8283
binary: &'static str,
84+
ipv6: bool,
8385
object: Option<Object>,
8486
action: Option<Action>,
8587
cmd_uid: Option<u32>,
@@ -90,12 +92,20 @@ impl IPRoute2Builder {
9092
pub fn new() -> Self {
9193
Self {
9294
binary: "ip",
95+
ipv6: false,
96+
object: None,
97+
action: None,
9398
cmd_uid: None,
9499
cmd_gid: None,
95-
..Default::default()
96100
}
97101
}
98102

103+
#[inline]
104+
pub fn ipv6(mut self) -> Self {
105+
self.ipv6 = true;
106+
self
107+
}
108+
99109
#[inline]
100110
pub fn object(mut self, object: Object) -> Self {
101111
self.object = Some(object);
@@ -141,6 +151,7 @@ impl IPRoute2Builder {
141151
pub fn build(&self) -> IPRoute2 {
142152
IPRoute2 {
143153
binary: self.binary,
154+
ipv6: self.ipv6,
144155
object: self.object,
145156
action: self.action,
146157
cmd_uid: self.cmd_uid,
@@ -150,6 +161,12 @@ impl IPRoute2Builder {
150161
}
151162

152163
impl IPRoute2 {
164+
#[inline]
165+
pub fn set_ipv6(mut self) -> Self {
166+
self.ipv6 = true;
167+
self
168+
}
169+
153170
#[inline]
154171
pub fn object(mut self, object: Object) -> Self {
155172
self.object = Some(object);
@@ -183,6 +200,9 @@ impl IPRoute2 {
183200
#[inline]
184201
pub fn command(&self) -> Result<Command> {
185202
let mut cmd = Command::new(self.binary);
203+
if self.ipv6 {
204+
cmd.arg("-6");
205+
}
186206
let object: &'static str = self
187207
.object
188208
.ok_or(IPRoute2Error::BuildCommand(

0 commit comments

Comments
 (0)