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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
use ipnet::IpNet;
use std::net::IpAddr;
mod rfc6890_entries;
#[derive(Debug)]
pub struct Rfc6890Entry {
pub address_block: IpNet,
pub name: String,
pub rfc: String,
pub allocation_date: String,
pub termination_date: String,
pub source: bool,
pub destination: bool,
pub forwardable: bool,
pub global: bool,
pub reserved_by_protocol: bool,
}
pub struct WithRfc6890 {
pub entries: Vec<Rfc6890Entry>,
}
impl WithRfc6890 {
pub fn create() -> WithRfc6890 { rfc6890_entries::entries() }
pub fn is_forwardable(&self, ip: &IpAddr) -> bool {
let most_specific = self.find_most_specific(ip);
if let Some(entry) = most_specific {
entry.forwardable
} else {
true
}
}
pub fn is_global(&self, ip: &IpAddr) -> bool {
let most_specific = self.find_most_specific(ip);
if let Some(entry) = most_specific {
entry.global
} else {
true
}
}
fn find_most_specific(&self, ip: &IpAddr) -> Option<&Rfc6890Entry> {
let mut most_specific: Option<&Rfc6890Entry> = None;
for cur in &self.entries {
if cur.address_block.contains(ip) {
if let Some(existing) = most_specific {
if existing.address_block.contains(&cur.address_block) {
most_specific = Some(cur);
}
} else {
most_specific = Some(cur);
}
}
}
most_specific
}
}
#[cfg(test)]
mod tests {
use crate::rfc::WithRfc6890;
use ipnet::IpNet;
use std::net::IpAddr;
#[test]
fn is_forwardable_or_not_192() {
let all: IpNet = "192.0.0.0/24".parse().unwrap();
let specific: IpNet = "192.0.0.0/29".parse().unwrap();
let rfc = WithRfc6890::create();
for ip_addr in all.hosts() {
let is_forwardable = specific.contains(&ip_addr);
assert_eq!(
is_forwardable,
rfc.is_forwardable(&ip_addr),
"failure on ip {}",
ip_addr
)
}
}
#[test]
fn is_global_192() {
let all: IpNet = "192.88.99.0/24".parse().unwrap();
let rfc = WithRfc6890::create();
for ip_addr in all.hosts() {
assert!(rfc.is_global(&ip_addr), "failure on ip {}", ip_addr)
}
}
#[test]
fn is_loopback() {
let ip: IpAddr = "127.0.0.1".parse().unwrap();
let rfc = WithRfc6890::create();
assert_eq!(false, rfc.is_forwardable(&ip))
}
}