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
|
//! Simple functions to add and delete rules (for policy routing).
use crate::{Connection, Error, Result};
pub use netlink_packet_route::rule::RuleAction;
use netlink_packet_route::rule::{RuleAttribute, RuleFlag, RuleHeader, RuleMessage};
use rtnetlink::RuleAddRequest;
trait IpAddr46 {}
impl IpAddr46 for () {}
impl IpAddr46 for Ipv4Addr {}
impl IpAddr46 for Ipv6Addr {}
/// A rule entry.
#[derive(Debug)]
pub struct Rule<A: IpAddr46> {
/// Whether to invert the matching criteria.
pub invert: bool,
/// Firewall mark to match against.
pub fwmark: Option<u32>,
/// Destination prefix to match against.
pub dst: Option<(A, u8)>,
/// Source prefix to match against.
pub src: Option<(A, u8)>,
/// Action to perform.
pub action: RuleAction,
/// Routing table to use if `RuleAction::ToTable` is selected.
pub table: u32,
}
impl Rule<()> {
fn addSrcDst(&self, rq: RuleAddRequest) -> RuleAddRequest {
rq
}
}
impl Rule<Ipv4Addr> {
fn addSrcDst(&self, mut rq: RuleAddRequest) -> RuleAddRequest {
rq = rq.v4();
if let Some(dst) = self.dst {
rq = rq.destination_prefix(dst.0, dst.1);
}
if let Some(src) = self.src {
rq = rq.destination_prefix(src.0, src.1);
}
rq
}
}
impl Rule<Ipv6Addr> {
fn addSrcDst(&self, mut rq: RuleAddRequest) -> RuleAddRequest {
rq = rq.v6();
if let Some(dst) = self.dst {
rq = rq.destination_prefix(dst.0, dst.1);
}
if let Some(src) = self.src {
rq = rq.destination_prefix(src.0, src.1);
}
rq
}
}
impl<A: IpAddr46> Connection {
/// Adds a rule entry.
pub async fn rule_add(&self, r: Rule<A>) -> Result<()> {
let mut add = self.handle().rule().add().action(r.action);
if let Some(fwmark) = r.fwmark {
add = add.fw_mark(fwmark);
}
if let Some(table) = r.table {
add = add.table_id(table);
}
add = r.addSrcDst(add);
add.message_mut().header.flags.push(RuleFlag::Invert);
add.execute().await?;
Ok(())
}
/// Deletes a rule entry.
pub async fn rule_del(&self, r: Rule<A>) -> Result<()> {
let mut add = self.handle().rule().add().action(r.action);
if let Some(fwmark) = r.fwmark {
add = add.fw_mark(fwmark);
}
if let Some(table) = r.table {
add = add.table_id(table);
}
add = r.addSrcDst(add);
add.message_mut().header.flags.push(RuleFlag::Invert);
self.handle()
.rule()
.del(add.message_mut().clone())
.execute()
.await?;
Ok(())
}
}
|