chiark / gitweb /
support v6 private addresses
[hippotat.git] / src / types.rs
1 // Copyright 2021 Ian Jackson and contributors to Hippotat
2 // SPDX-License-Identifier: GPL-3.0-or-later
3 // There is NO WARRANTY.
4
5 use crate::prelude::*;
6
7 #[derive(Debug,Copy,Clone)]
8 pub enum LinkEnd { Server, Client }
9
10 #[derive(Debug,Clone,Hash,Eq,PartialEq,Ord,PartialOrd)]
11 pub struct ServerName(pub String);
12
13 #[derive(Debug,Clone,Copy,Hash,Eq,PartialEq,Ord,PartialOrd)]
14 pub struct ClientName(pub IpAddr);
15
16 #[derive(Debug,Clone,Hash,Eq,PartialEq,Ord,PartialOrd)]
17 pub struct LinkName {
18   pub server: ServerName,
19   pub client: ClientName,
20 }
21
22 impl FromStr for ClientName {
23   type Err = AE;
24   #[throws(AE)]
25   fn from_str(s: &str) -> Self {
26     ClientName(
27       if let Ok(v4addr) = s.parse::<Ipv4Addr>() {
28         if s != v4addr.to_string() {
29           throw!(anyhow!("invalid client name (unusual IPv4 address syntax)"));
30         }
31         v4addr.into()
32       } else if let Ok(v6addr) = s.parse::<Ipv6Addr>() {
33         if s != v6addr.to_string() {
34           throw!(anyhow!("invalid client name (non-canonical IPv6 address)"));
35         }
36         v6addr.into()
37       } else {
38         throw!(anyhow!("invalid client name (IPv4 or IPv6 address)"))
39       }
40     )
41   }
42 }
43
44 impl FromStr for ServerName {
45   type Err = AE;
46   #[throws(AE)]
47   fn from_str(s: &str) -> Self {
48     if ! regex_is_match!(r"
49         ^ (?: SERVER
50             | [0-9a-z][-0-9a-z]* (:? \.
51               [0-9a-z][-0-9a-z]*        )*
52           ) $"x, s) {
53       throw!(anyhow!("bad syntax for server name"));
54     }
55     if ! regex_is_match!(r"[A-Za-z-]", s) {
56       throw!(anyhow!("bad syntax for server name \
57                       (too much like an IPv4 address)"));
58     }
59     ServerName(s.into())
60   }
61 }
62
63 impl Display for ServerName {
64   #[throws(fmt::Error)]
65   fn fmt(&self, f: &mut fmt::Formatter) { Display::fmt(&self.0, f)?; }
66 }
67 impl Display for ClientName {
68   #[throws(fmt::Error)]
69   fn fmt(&self, f: &mut fmt::Formatter) { Display::fmt(&self.0, f)?; }
70 }
71 impl Display for LinkName {
72   #[throws(fmt::Error)]
73   fn fmt(&self, f: &mut fmt::Formatter) {
74     write!(f, "[{} {}]", &self.server, &self.client)?;
75   }
76 }