1use std::net::Ipv4Addr;
9use std::net::Ipv6Addr;
10use std::str::FromStr;
11use std::hash::Hash;
12use std::error::Error;
13use std::fmt;
14
15const IPV4_BIT_LENGTH: u8 = 32;
16const IPV6_BIT_LENGTH: u8 = 128;
17
18pub trait Addressable
22where Self: Clone,
23 Self: FromStr,
24 Self: ToString,
25 Self: Hash,
26 Self: Eq,
27 Self: fmt::Debug,
28{
29 fn bit_len() -> u8;
31
32 fn byte_len() -> u8 {
34 Self::bit_len() / 8
35 }
36
37 fn empty_new() -> Self;
39
40 fn from_slice(s: &[u8]) -> Self;
42
43 fn octets_ref(&self) -> &[u8];
45}
46
47impl Addressable for Ipv4Addr {
49
50 fn bit_len() -> u8 {
52 IPV4_BIT_LENGTH
53 }
54
55 fn empty_new() -> Self {
57 Ipv4Addr::UNSPECIFIED
58 }
59
60 fn from_slice(s: &[u8]) -> Self {
62 let t: [u8; 4] = [s[0], s[1], s[2], s[3]];
63
64 Ipv4Addr::from(t)
65 }
66
67 fn octets_ref(&self) -> &[u8] {
69 let p = (self as *const Ipv4Addr) as *const u8;
70 unsafe {
71 std::slice::from_raw_parts(p, std::mem::size_of::<Ipv4Addr>())
72 }
73 }
74}
75
76impl Addressable for Ipv6Addr {
78
79 fn bit_len() -> u8 {
81 IPV6_BIT_LENGTH
82 }
83
84 fn empty_new() -> Self {
86 Ipv6Addr::UNSPECIFIED
87 }
88
89 fn from_slice(s: &[u8]) -> Self {
91 let t: [u8; 16] = [s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7],
92 s[8], s[9], s[10], s[11], s[12], s[13], s[14], s[15]];
93
94 Ipv6Addr::from(t)
95 }
96
97 fn octets_ref(&self) -> &[u8] {
99 let p = (self as *const Ipv6Addr) as *const u8;
100 unsafe {
101 std::slice::from_raw_parts(p, std::mem::size_of::<Ipv4Addr>())
102 }
103 }
104}
105
106pub trait Prefixable {
110
111 fn from_prefix(p: &Self) -> Self;
113
114 fn from_common(prefix1: &Self, prefix2: &Self) -> Self;
116
117 fn len(&self) -> u8;
119
120 fn bit_at(&self, index: u8) -> u8 {
122 let offset = index / 8;
123 let shift = 7 - (index % 8);
124 let octets = self.octets();
125
126 (octets[offset as usize] >> shift) & 0x1
127 }
128
129 fn octets(&self) -> &[u8];
131
132 fn octets_mut(&mut self) -> &mut [u8];
134
135 fn contains(&self, prefix: &Self) -> bool {
137 if self.len() > prefix.len() {
138 return false
139 }
140
141 let np = self.octets();
142 let pp = prefix.octets();
143
144 let mut offset: usize = self.len() as usize / 8;
145 let shift: usize = self.len() as usize % 8;
146
147 if shift > 0 {
148 if (MASKBITS[shift] & (np[offset] ^ pp[offset])) > 0 {
149 return false
150 }
151 }
152
153 while offset > 0 {
154 offset -= 1;
155 if np[offset] != pp[offset] {
156 return false
157 }
158 }
159
160 return true
161 }
162}
163
164const PLEN2MASK: [[u8; 4]; 32] = [
168 [0x00, 0x00, 0x00, 0x00],
169 [0x80, 0x00, 0x00, 0x00],
170 [0xc0, 0x00, 0x00, 0x00],
171 [0xe0, 0x00, 0x00, 0x00],
172 [0xf0, 0x00, 0x00, 0x00],
173 [0xf8, 0x00, 0x00, 0x00],
174 [0xfc, 0x00, 0x00, 0x00],
175 [0xfe, 0x00, 0x00, 0x00],
176
177 [0xff, 0x00, 0x00, 0x00],
178 [0xff, 0x80, 0x00, 0x00],
179 [0xff, 0xc0, 0x00, 0x00],
180 [0xff, 0xe0, 0x00, 0x00],
181 [0xff, 0xf0, 0x00, 0x00],
182 [0xff, 0xf8, 0x00, 0x00],
183 [0xff, 0xfc, 0x00, 0x00],
184 [0xff, 0xfe, 0x00, 0x00],
185
186 [0xff, 0xff, 0x00, 0x00],
187 [0xff, 0xff, 0x80, 0x00],
188 [0xff, 0xff, 0xc0, 0x00],
189 [0xff, 0xff, 0xe0, 0x00],
190 [0xff, 0xff, 0xf0, 0x00],
191 [0xff, 0xff, 0xf8, 0x00],
192 [0xff, 0xff, 0xfc, 0x00],
193 [0xff, 0xff, 0xfe, 0x00],
194
195 [0xff, 0xff, 0xff, 0x00],
196 [0xff, 0xff, 0xff, 0x80],
197 [0xff, 0xff, 0xff, 0xc0],
198 [0xff, 0xff, 0xff, 0xe0],
199 [0xff, 0xff, 0xff, 0xf0],
200 [0xff, 0xff, 0xff, 0xf8],
201 [0xff, 0xff, 0xff, 0xfc],
202 [0xff, 0xff, 0xff, 0xfe],
203];
204
205const PLEN2MASK6: [u16; 16] = [
206 0x0000,
207 0x8000,
208 0xc000,
209 0xe000,
210 0xf000,
211 0xf800,
212 0xfc00,
213 0xfe00,
214
215 0xff00,
216 0xff80,
217 0xffc0,
218 0xffe0,
219 0xfff0,
220 0xfff8,
221 0xfffc,
222 0xfffe,
223];
224
225const MASKBITS: [u8; 9] = [
226 0x00, 0x80, 0xc0, 0xe0,
227 0xf0, 0xf8, 0xfc, 0xfe, 0xff
228];
229
230fn slice_get_u32(s: &[u8], i: usize) -> u32 {
232 ((s[i] as u32) << 24) | ((s[i + 1] as u32) << 16) | ((s[i + 2] as u32) << 8) | s[i + 3] as u32
233}
234
235fn slice_copy_u32(s: &mut [u8], v: u32, i: usize) {
237 s[i + 0] = ((v >> 24) & 0xFF) as u8;
238 s[i + 1] = ((v >> 16) & 0xFF) as u8;
239 s[i + 2] = ((v >> 8) & 0xFF) as u8;
240 s[i + 3] = (v & 0xFF) as u8;
241}
242
243#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
247pub struct Prefix<T: Addressable> {
248
249 address: T,
251
252 len: u8,
254}
255
256
257impl<T: Addressable> Prefixable for Prefix<T> {
258
259 fn from_prefix(p: &Self) -> Self {
261 Self {
262 address: p.address.clone(),
263 len: p.len
264 }
265 }
266
267 fn from_common(prefix1: &Self, prefix2: &Self) -> Self {
269 let p1 = prefix1.octets();
270 let p2 = prefix2.octets();
271 let mut i = 0u8;
272 let mut j = 0u8;
273 let mut pcommon = Self { address: T::empty_new(), len: 0 };
274 let px = pcommon.octets_mut();
275 let bytes = T::bit_len() / 8;
276
277 while i < bytes {
278 let l1: u32 = slice_get_u32(p1, i as usize);
279 let l2: u32 = slice_get_u32(p2, i as usize);
280 let cp: u32 = l1 ^ l2;
281 if cp == 0 {
282 slice_copy_u32(px, l1, i as usize);
283 }
284 else {
285 j = cp.leading_zeros() as u8;
286 let (mask, _) = match j {
287 0 => (0, false),
288 _ => 0xFFFFFFFFu32.overflowing_shl((32 - j) as u32),
289 };
290 let v = l1 & (mask as u32);
291
292 slice_copy_u32(px, v, i as usize);
293 break;
294 }
295
296 i += 4;
297 }
298
299 pcommon.len = if prefix2.len() > i * 8 + j {
300 i * 8 + j
301 } else {
302 prefix2.len()
303 };
304
305 pcommon
306 }
307
308 fn len(&self) -> u8 {
310 self.len
311 }
312
313 fn octets(&self) -> &[u8] {
315 let p = (&self.address as *const T) as *const u8;
316 unsafe {
317 std::slice::from_raw_parts(p, std::mem::size_of::<T>())
318 }
319 }
320
321 fn octets_mut(&mut self) -> &mut [u8] {
323 let p = (&mut self.address as *mut T) as *mut u8;
324 unsafe {
325 std::slice::from_raw_parts_mut(p, std::mem::size_of::<T>())
326 }
327 }
328}
329
330impl<T: Addressable> Prefix<T>
334{
335
336 pub fn new() -> Self {
338 Self {
339 address: T::empty_new(),
340 len: 0,
341 }
342 }
343
344 pub fn from(address: T, len: u8) -> Self {
346 Self {
347 address: address,
348 len: len,
349 }
350 }
351
352 pub fn from_slice(slice: &[u8], prefix_len: u8) -> Self{
354 Self {
355 address: T::from_slice(slice),
356 len: prefix_len,
357 }
358 }
359
360 pub fn from_str(s: &str) -> Result<Prefix<T>, PrefixParseError> {
362 let (pos, prefix_len) = match s.find('/') {
363 Some(pos) => {
365 match s[pos + 1..].parse::<u8>() {
366 Ok(prefix_len) if prefix_len <= T::bit_len() => (pos, prefix_len),
367 _ => return Err(PrefixParseError(())),
368 }
369 },
370 None => (s.len(), T::bit_len()),
372 };
373
374 let address_str = &s[..pos];
375 match T::from_str(address_str) {
376 Ok(address) =>
377 Ok(Prefix::<T> {
378 address: address,
379 len: prefix_len,
380 }),
381 Err(_) => Err(PrefixParseError(())),
382 }
383 }
384
385 pub fn address(&self) -> &T {
387 &self.address
388 }
389}
390
391impl Prefix<Ipv4Addr> {
393 pub fn apply_mask(&mut self) {
395 if self.len < Ipv4Addr::bit_len() {
396 let octets = self.address().octets();
397 let mask = &PLEN2MASK[self.len as usize];
398 self.address = Ipv4Addr::new(octets[0] & mask[0],
399 octets[1] & mask[1],
400 octets[2] & mask[2],
401 octets[3] & mask[3]);
402 }
403 }
404}
405
406impl Prefix<Ipv6Addr> {
408 pub fn apply_mask(&mut self) {
410 fn mask4segment(s: u8, len: u8) -> u16 {
411 if len >= s * 16 {
412 let offset = len - s * 16;
413 if offset >= 16 {
414 0xffff
415 }
416 else {
417 PLEN2MASK6[offset as usize]
418 }
419 }
420 else {
421 0
422 }
423 }
424
425 if self.len < Ipv6Addr::bit_len() {
426 let segments = self.address().segments();
427 self.address = Ipv6Addr::new(segments[0] & mask4segment(0, self.len),
428 segments[1] & mask4segment(1, self.len),
429 segments[2] & mask4segment(2, self.len),
430 segments[3] & mask4segment(3, self.len),
431 segments[4] & mask4segment(4, self.len),
432 segments[5] & mask4segment(5, self.len),
433 segments[6] & mask4segment(6, self.len),
434 segments[7] & mask4segment(7, self.len));
435 }
436 }
437}
438
439impl<T: Addressable> fmt::Display for Prefix<T>
440{
441 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
442 write!(fmt, "{}/{}", self.address.to_string(), self.len)
443 }
444}
445
446pub fn prefix_ipv4_from(addr_str: &str, mask_str: &str) -> Result<Prefix<Ipv4Addr>, PrefixParseError> {
448 match Ipv4Addr::from_str(addr_str) {
449 Err(_) => Err(PrefixParseError(())),
450 Ok(addr) => {
451 match Ipv4Addr::from_str(mask_str) {
452 Err(_) => Err(PrefixParseError(())),
453 Ok(mask) => {
454 let mask = u32::from(mask);
455 Ok(Prefix::<Ipv4Addr>::from(addr, (32 - mask.trailing_zeros()) as u8))
456 },
457 }
458 }
459 }
460}
461
462#[derive(Debug, Clone, PartialEq, Eq)]
466pub struct PrefixParseError(());
467
468impl fmt::Display for PrefixParseError {
469 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
470 fmt.write_str(self.description())
471 }
472}
473
474impl Error for PrefixParseError {
475 fn description(&self) -> &str {
476 "invalid IP prefix syntax"
477 }
478}
479
480#[cfg(test)]
484mod tests {
485 use std::collections::BTreeMap;
486 use super::*;
487
488 #[test]
489 pub fn test_octets() {
490 let p = Prefix::<Ipv4Addr>::from_str("1.2.3.4/24").unwrap();
491 let o = p.octets();
492 assert_eq!(o, &[1, 2, 3, 4]);
493
494 let p = Prefix::<Ipv6Addr>::from_str("2001:1:2::7:8/48").unwrap();
495 let o = p.octets();
496 assert_eq!(o, &[0x20, 1, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 7, 0, 8]);
497 }
498
499 #[test]
500 pub fn test_prefix_ipv4() {
501 let p = Prefix::<Ipv4Addr>::from_str("10.10.10.0/24").unwrap();
502 assert_eq!(p.address().octets(), [10, 10, 10, 0]);
503 assert_eq!(p.to_string(), "10.10.10.0/24");
504
505 let p = Prefix::<Ipv4Addr>::from_str("1.2.3.4").unwrap();
506 assert_eq!(p.address().octets(), [1, 2, 3, 4]);
507 assert_eq!(p.to_string(), "1.2.3.4/32");
508
509 let mut p = Prefix::<Ipv4Addr>::from_str("1.2.3.4/24").unwrap();
510 assert_eq!(p.address().octets(), [1, 2, 3, 4]);
511 assert_eq!(p.to_string(), "1.2.3.4/24");
512 p.apply_mask();
513 assert_eq!(p.address().octets(), [1, 2, 3, 0]);
514 assert_eq!(p.to_string(), "1.2.3.0/24");
515
516 let mut p = Prefix::<Ipv4Addr>::from_str("172.16.0.1/16").unwrap();
517 assert_eq!(p.address().octets(), [172, 16, 0, 1]);
518 assert_eq!(p.to_string(), "172.16.0.1/16");
519 p.apply_mask();
520 assert_eq!(p.address().octets(), [172, 16, 0, 0]);
521 assert_eq!(p.to_string(), "172.16.0.0/16");
522
523 let p = Prefix::<Ipv4Addr>::from_slice(&[172, 16, 0, 1], 24);
524 assert_eq!(p.to_string(), "172.16.0.1/24");
525
526 match Prefix::<Ipv4Addr>::from_str("10.10.10.10/33") {
527 Ok(_) => assert!(false, "Should return error"),
528 Err(_err) => { }
529 }
530 }
531
532 #[test]
533 pub fn test_prefix_ipv4_common() {
534 let p1 = Prefix::<Ipv4Addr>::from_str("10.10.10.0/24").unwrap();
535 let p2 = Prefix::<Ipv4Addr>::from_str("10.10.11.0/24").unwrap();
536 let pc = Prefix::<Ipv4Addr>::from_common(&p1, &p2);
537 assert_eq!(pc.to_string(), "10.10.10.0/23");
538
539 let p1 = Prefix::<Ipv4Addr>::from_str("10.10.10.0/24").unwrap();
540 let p2 = Prefix::<Ipv4Addr>::from_str("10.10.0.0/16").unwrap();
541 let pc = Prefix::<Ipv4Addr>::from_common(&p1, &p2);
542 assert_eq!(pc.to_string(), "10.10.0.0/16");
543
544 let p1 = Prefix::<Ipv4Addr>::from_str("192.168.0.0/24").unwrap();
545 let p2 = Prefix::<Ipv4Addr>::from_str("10.10.10.0/24").unwrap();
546 let pc = Prefix::<Ipv4Addr>::from_common(&p1, &p2);
547 assert_eq!(pc.to_string(), "0.0.0.0/0");
548
549 let p1 = Prefix::<Ipv4Addr>::from_str("192.168.0.0/24").unwrap();
550 let p2 = Prefix::<Ipv4Addr>::from_str("128.10.10.0/24").unwrap();
551 let pc = Prefix::<Ipv4Addr>::from_common(&p1, &p2);
552 assert_eq!(pc.to_string(), "128.0.0.0/1");
553 }
554
555 #[test]
556 pub fn test_prefix_ipv4_sort() {
557 let mut map = BTreeMap::new();
558
559 let p1 = Prefix::<Ipv4Addr>::from_str("10.10.10.0/24").unwrap();
560 let p2 = Prefix::<Ipv4Addr>::from_str("10.10.11.0/24").unwrap();
561 let p3 = Prefix::<Ipv4Addr>::from_common(&p1, &p2);
562 let p4 = Prefix::<Ipv4Addr>::from_str("10.10.10.0/24").unwrap();
565 let p5 = Prefix::<Ipv4Addr>::from_str("10.10.0.0/16").unwrap();
566 let p6 = Prefix::<Ipv4Addr>::from_common(&p4, &p5);
567 let p7 = Prefix::<Ipv4Addr>::from_str("192.168.0.0/24").unwrap();
570 let p8 = Prefix::<Ipv4Addr>::from_str("10.10.10.0/24").unwrap();
571 let p9 = Prefix::<Ipv4Addr>::from_common(&p7, &p8);
572 let p10 = Prefix::<Ipv4Addr>::from_str("192.168.0.0/24").unwrap();
575 let p11 = Prefix::<Ipv4Addr>::from_str("128.10.10.0/24").unwrap();
576 let p12 = Prefix::<Ipv4Addr>::from_common(&p10, &p11);
577 map.insert(p1, 1);
580 map.insert(p2, 2);
581 map.insert(p3, 3);
582
583 map.insert(p5, 5);
584
585 map.insert(p7, 7);
586
587 map.insert(p9, 9);
588
589 map.insert(p11, 11);
590 map.insert(p12, 12);
591
592 let v: Vec<_> = map.iter().map(|(k, v)| v).collect();
593 assert_eq!(v, vec![&9, &5, &3, &1, &2, &12, &11, &7]);
594 }
595
596 #[test]
597 pub fn test_prefix_ipv6() {
598 let p = Prefix::<Ipv6Addr>::from_str("::/0").unwrap();
599 assert_eq!(p.address().segments(), [0, 0, 0, 0, 0, 0, 0, 0]);
600 assert_eq!(p.to_string(), "::/0");
601
602 let p = Prefix::<Ipv6Addr>::from_str("2001:1234::/48").unwrap();
603 assert_eq!(p.address().segments(), [0x2001, 0x1234, 0, 0, 0, 0, 0, 0]);
604 assert_eq!(p.to_string(), "2001:1234::/48");
605
606 let mut p = Prefix::<Ipv6Addr>::from_str("2001:1234::567/48").unwrap();
607 assert_eq!(p.address().segments(), [0x2001, 0x1234, 0, 0, 0, 0, 0, 0x567]);
608 assert_eq!(p.to_string(), "2001:1234::567/48");
609 p.apply_mask();
610 assert_eq!(p.address().segments(), [0x2001, 0x1234, 0, 0, 0, 0, 0, 0]);
611 assert_eq!(p.to_string(), "2001:1234::/48");
612
613 let mut p = Prefix::<Ipv6Addr>::from_str("2001:1234::ffff/124").unwrap();
614 p.apply_mask();
615 assert_eq!(p.address().segments(), [0x2001, 0x1234, 0, 0, 0, 0, 0, 0xfff0]);
616 assert_eq!(p.to_string(), "2001:1234::fff0/124");
617
618 let mut p = Prefix::<Ipv6Addr>::from_str("2001:1234::ffff/120").unwrap();
619 p.apply_mask();
620 assert_eq!(p.address().segments(), [0x2001, 0x1234, 0, 0, 0, 0, 0, 0xff00]);
621 assert_eq!(p.to_string(), "2001:1234::ff00/120");
622
623 let p = Prefix::<Ipv6Addr>::from_slice(&[0x20, 0x01, 0x12, 0x34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 48);
624 assert_eq!(p.to_string(), "2001:1234::/48");
625
626 match Prefix::<Ipv6Addr>::from_str("2001:1234::/130") {
627 Ok(_) => assert!(false, "Should return error"),
628 Err(_err) => { }
629 }
630 }
631}