Mercurial > crates > systemd-socket
annotate src/resolv_addr.rs @ 26:0feab4f4c2ce
Relax version requirements and update MSRV
The MSRV was accidentally increased without documentation. Increase
itself is fine since it satisfies "latest stable Debian" condition but
given there are soundness issues this relaxes the version requirements
to work on 1.48 and also documents it.
| author | Martin Habovstiak <martin.habovstiak@gmail.com> |
|---|---|
| date | Fri, 28 Feb 2025 23:10:11 +0100 |
| parents | 66c0e10c89fc |
| children | cfef4593e207 |
| rev | line source |
|---|---|
|
4
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
1 use thiserror::Error; |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
2 use std::fmt; |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
3 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
4 #[derive(Debug, PartialEq)] |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
5 pub(crate) struct ResolvAddr(String); |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
6 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
7 impl ResolvAddr { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
8 pub(crate) fn as_str(&self) -> &str { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
9 &self.0 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
10 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
11 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
12 pub(crate) fn try_from_generic<T: std::ops::Deref<Target=str> + Into<String>>(string: T) -> Result<Self, ResolvAddrError> { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
13 // can't use a combinator due to borrowing |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
14 let colon = match string.rfind(':') { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
15 Some(colon) => colon, |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
16 None => return Err(ResolvAddrError::MissingPort(string.into())), |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
17 }; |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
18 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
19 let (hostname, port) = string.split_at(colon); |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
20 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
21 if let Err(error) = port[1..].parse::<u16>() { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
22 return Err(ResolvAddrError::InvalidPort { string: string.into(), error, }); |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
23 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
24 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
25 let len = hostname.len(); |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
26 if len > 253 { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
27 return Err(ResolvAddrError::TooLong { string: string.into(), len, } ) |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
28 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
29 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
30 let mut label_start = 0usize; |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
31 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
32 for (i, c) in hostname.chars().enumerate() { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
33 match c { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
34 '.' => { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
35 if i - label_start == 0 { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
36 return Err(ResolvAddrError::EmptyLabel { string: string.into(), label_start, }); |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
37 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
38 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
39 label_start = i + 1; |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
40 }, |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
41 'a'..='z' | 'A'..='Z' | '0'..='9' | '-' => (), |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
42 _ => return Err(ResolvAddrError::InvalidCharacter { string: string.into(), c, pos: i, }), |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
43 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
44 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
45 if i - label_start > 63 { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
46 return Err(ResolvAddrError::LongLabel { string: string.into(), label_start, label_end: i, }); |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
47 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
48 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
49 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
50 Ok(ResolvAddr(string.into())) |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
51 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
52 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
53 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
54 impl fmt::Display for ResolvAddr { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
55 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
56 fmt::Display::fmt(&self.0, f) |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
57 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
58 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
59 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
60 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
61 #[derive(Debug, Error)] |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
62 pub(crate) enum ResolvAddrError { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
63 #[error("hostname {string} has {len} character which exceeds the limit of 253")] |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
64 TooLong { string: String, len: usize }, |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
65 #[error("invalid character {c} in hostname {string} at position {pos}")] |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
66 InvalidCharacter { string: String, pos: usize, c: char, }, |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
67 #[error("hostname {string} contains a label {} at position {label_start} which is {} characters long - more than the limit 63", &string[(*label_start)..(*label_end)], label_end - label_start)] |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
68 LongLabel { string: String, label_start: usize, label_end: usize, }, |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
69 #[error("hostname {string} contains an empty label at position {label_start}")] |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
70 EmptyLabel { string: String, label_start: usize, }, |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
71 #[error("the address {0} is missing a port")] |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
72 MissingPort(String), |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
73 #[error("failed to parse port numer in the address {string}")] |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
74 InvalidPort { string: String, error: std::num::ParseIntError, }, |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
75 } |
