Skip to main content

max / makenotwork

pom: bump hickory-resolver to 0.26 0.26 drops enum-as-inner, so RData no longer has as_a()/as_cname() accessors, and the typed lookups (ipv4_lookup, mx_lookup, txt_lookup) now all return a plain Lookup rather than a typed one. Extraction goes through answers() with an explicit variant match per record type. ResolverBuilder::build also became fallible. Verified live against all five record types: A, AAAA, CNAME, MX, TXT. 456 tests green, clippy clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-07-22 18:23 UTC
Commit: 3b30fd4ea34890a340999dcd13691d6384a17936
Parent: c517da4
3 files changed, +128 insertions, -38 deletions
M pom/Cargo.lock +86 -23
@@ -441,6 +441,16 @@ dependencies = [
441 441
442 442 [[package]]
443 443 name = "core-foundation"
444 + version = "0.9.4"
445 + source = "registry+https://github.com/rust-lang/crates.io-index"
446 + checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
447 + dependencies = [
448 + "core-foundation-sys",
449 + "libc",
450 + ]
451 +
452 + [[package]]
453 + name = "core-foundation"
444 454 version = "0.10.1"
445 455 source = "registry+https://github.com/rust-lang/crates.io-index"
446 456 checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6"
@@ -679,18 +689,6 @@ dependencies = [
679 689 ]
680 690
681 691 [[package]]
682 - name = "enum-as-inner"
683 - version = "0.6.1"
684 - source = "registry+https://github.com/rust-lang/crates.io-index"
685 - checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc"
686 - dependencies = [
687 - "heck",
688 - "proc-macro2",
689 - "quote",
690 - "syn",
691 - ]
692 -
693 - [[package]]
694 692 name = "equivalent"
695 693 version = "1.0.2"
696 694 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -963,46 +961,70 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
963 961 checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
964 962
965 963 [[package]]
966 - name = "hickory-proto"
967 - version = "0.25.2"
964 + name = "hickory-net"
965 + version = "0.26.1"
968 966 source = "registry+https://github.com/rust-lang/crates.io-index"
969 - checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502"
967 + checksum = "e2295ed2f9c31e471e1428a8f88a3f0e1f4b27c15049592138d1eebe9c35b183"
970 968 dependencies = [
971 969 "async-trait",
972 970 "cfg-if",
973 971 "data-encoding",
974 - "enum-as-inner",
975 972 "futures-channel",
976 973 "futures-io",
977 974 "futures-util",
975 + "hickory-proto",
978 976 "idna",
979 977 "ipnet",
978 + "jni",
979 + "rand 0.10.2",
980 + "thiserror 2.0.18",
981 + "tinyvec",
982 + "tokio",
983 + "tracing",
984 + "url",
985 + ]
986 +
987 + [[package]]
988 + name = "hickory-proto"
989 + version = "0.26.1"
990 + source = "registry+https://github.com/rust-lang/crates.io-index"
991 + checksum = "0bab31817bfb44672a252e97fe81cd0c18d1b2cf892108922f6818820df8c643"
992 + dependencies = [
993 + "data-encoding",
994 + "idna",
995 + "ipnet",
996 + "jni",
980 997 "once_cell",
981 - "rand 0.9.2",
998 + "prefix-trie",
999 + "rand 0.10.2",
982 1000 "ring",
983 1001 "thiserror 2.0.18",
984 1002 "tinyvec",
985 - "tokio",
986 1003 "tracing",
987 1004 "url",
988 1005 ]
989 1006
990 1007 [[package]]
991 1008 name = "hickory-resolver"
992 - version = "0.25.2"
1009 + version = "0.26.1"
993 1010 source = "registry+https://github.com/rust-lang/crates.io-index"
994 - checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a"
1011 + checksum = "f0d58d28879ceecde6607729660c2667a081ccdc082e082675042793960f178c"
995 1012 dependencies = [
996 1013 "cfg-if",
997 1014 "futures-util",
1015 + "hickory-net",
998 1016 "hickory-proto",
999 1017 "ipconfig",
1018 + "ipnet",
1019 + "jni",
1000 1020 "moka",
1021 + "ndk-context",
1001 1022 "once_cell",
1002 1023 "parking_lot",
1003 - "rand 0.9.2",
1024 + "rand 0.10.2",
1004 1025 "resolv-conf",
1005 1026 "smallvec",
1027 + "system-configuration",
1006 1028 "thiserror 2.0.18",
1007 1029 "tokio",
1008 1030 "tracing",
@@ -1313,6 +1335,9 @@ name = "ipnet"
1313 1335 version = "2.12.0"
1314 1336 source = "registry+https://github.com/rust-lang/crates.io-index"
1315 1337 checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2"
1338 + dependencies = [
1339 + "serde",
1340 + ]
1316 1341
1317 1342 [[package]]
1318 1343 name = "iri-string"
@@ -1542,6 +1567,12 @@ dependencies = [
1542 1567 ]
1543 1568
1544 1569 [[package]]
1570 + name = "ndk-context"
1571 + version = "0.1.1"
1572 + source = "registry+https://github.com/rust-lang/crates.io-index"
1573 + checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b"
1574 +
1575 + [[package]]
1545 1576 name = "nom"
1546 1577 version = "7.1.3"
1547 1578 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1774,6 +1805,17 @@ dependencies = [
1774 1805 ]
1775 1806
1776 1807 [[package]]
1808 + name = "prefix-trie"
1809 + version = "0.8.4"
1810 + source = "registry+https://github.com/rust-lang/crates.io-index"
1811 + checksum = "4cf6e3177f0684016a5c209b00882e15f8bdd3f3bb48f0491df10cd102d0c6e7"
1812 + dependencies = [
1813 + "either",
1814 + "ipnet",
1815 + "num-traits",
1816 + ]
1817 +
1818 + [[package]]
1777 1819 name = "prettyplease"
1778 1820 version = "0.2.37"
1779 1821 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2122,7 +2164,7 @@ version = "0.7.0"
2122 2164 source = "registry+https://github.com/rust-lang/crates.io-index"
2123 2165 checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0"
2124 2166 dependencies = [
2125 - "core-foundation",
2167 + "core-foundation 0.10.1",
2126 2168 "core-foundation-sys",
2127 2169 "jni",
2128 2170 "log",
@@ -2222,7 +2264,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
2222 2264 checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
2223 2265 dependencies = [
2224 2266 "bitflags",
2225 - "core-foundation",
2267 + "core-foundation 0.10.1",
2226 2268 "core-foundation-sys",
2227 2269 "libc",
2228 2270 "security-framework-sys",
@@ -2680,6 +2722,27 @@ dependencies = [
2680 2722 ]
2681 2723
2682 2724 [[package]]
2725 + name = "system-configuration"
2726 + version = "0.7.0"
2727 + source = "registry+https://github.com/rust-lang/crates.io-index"
2728 + checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b"
2729 + dependencies = [
2730 + "bitflags",
2731 + "core-foundation 0.9.4",
2732 + "system-configuration-sys",
2733 + ]
2734 +
2735 + [[package]]
2736 + name = "system-configuration-sys"
2737 + version = "0.6.0"
2738 + source = "registry+https://github.com/rust-lang/crates.io-index"
2739 + checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4"
2740 + dependencies = [
2741 + "core-foundation-sys",
2742 + "libc",
2743 + ]
2744 +
2745 + [[package]]
2683 2746 name = "tagptr"
2684 2747 version = "0.2.0"
2685 2748 source = "registry+https://github.com/rust-lang/crates.io-index"
M pom/Cargo.toml +1 -1
@@ -56,7 +56,7 @@ uuid = { version = "1", features = ["v4"] }
56 56 hostname = "0.4"
57 57
58 58 # DNS resolution
59 - hickory-resolver = "0.25"
59 + hickory-resolver = "0.26"
60 60
61 61 # TLS certificate checking
62 62 x509-parser = "0.16"
@@ -2,7 +2,8 @@
2 2
3 3 use std::collections::HashSet;
4 4
5 - use hickory_resolver::TokioResolver;
5 + use hickory_resolver::proto::rr::RData;
6 + use hickory_resolver::{ResolverBuilder, TokioResolver};
6 7 use tracing::instrument;
7 8
8 9 use crate::config::DnsRecord;
@@ -12,8 +13,8 @@ use crate::types::{DnsCheckResult, DnsRecordType};
12 13 /// Returns one `DnsCheckResult` per `DnsRecord` in the input.
13 14 #[instrument(skip_all)]
14 15 pub async fn check_dns(target: &str, records: &[DnsRecord]) -> Vec<DnsCheckResult> {
15 - let resolver = match TokioResolver::builder_tokio() {
16 - Ok(builder) => builder.build(),
16 + let resolver = match TokioResolver::builder_tokio().and_then(ResolverBuilder::build) {
17 + Ok(resolver) => resolver,
17 18 Err(e) => {
18 19 return records
19 20 .iter()
@@ -92,7 +93,12 @@ async fn resolve_a(resolver: &TokioResolver, name: &str) -> Result<Vec<String>,
92 93 .ipv4_lookup(name)
93 94 .await
94 95 .map_err(|e| format!("A lookup failed for {name}: {e}"))?;
95 - Ok(response.iter().map(|ip| ip.to_string()).collect())
96 + Ok(rdata(&response)
97 + .filter_map(|d| match d {
98 + RData::A(a) => Some(a.0.to_string()),
99 + _ => None,
100 + })
101 + .collect())
96 102 }
97 103
98 104 async fn resolve_aaaa(resolver: &TokioResolver, name: &str) -> Result<Vec<String>, String> {
@@ -100,7 +106,12 @@ async fn resolve_aaaa(resolver: &TokioResolver, name: &str) -> Result<Vec<String
100 106 .ipv6_lookup(name)
101 107 .await
102 108 .map_err(|e| format!("AAAA lookup failed for {name}: {e}"))?;
103 - Ok(response.iter().map(|ip| ip.to_string()).collect())
109 + Ok(rdata(&response)
110 + .filter_map(|d| match d {
111 + RData::AAAA(aaaa) => Some(aaaa.0.to_string()),
112 + _ => None,
113 + })
114 + .collect())
104 115 }
105 116
106 117 async fn resolve_cname(resolver: &TokioResolver, name: &str) -> Result<Vec<String>, String> {
@@ -108,11 +119,10 @@ async fn resolve_cname(resolver: &TokioResolver, name: &str) -> Result<Vec<Strin
108 119 .lookup(name, hickory_resolver::proto::rr::RecordType::CNAME)
109 120 .await
110 121 .map_err(|e| format!("CNAME lookup failed for {name}: {e}"))?;
111 - Ok(response
112 - .iter()
113 - .filter_map(|r| {
114 - r.as_cname()
115 - .map(|c| c.0.to_string().trim_end_matches('.').to_string())
122 + Ok(rdata(&response)
123 + .filter_map(|d| match d {
124 + RData::CNAME(c) => Some(trim_root(&c.0.to_string())),
125 + _ => None,
116 126 })
117 127 .collect())
118 128 }
@@ -122,9 +132,11 @@ async fn resolve_mx(resolver: &TokioResolver, name: &str) -> Result<Vec<String>,
122 132 .mx_lookup(name)
123 133 .await
124 134 .map_err(|e| format!("MX lookup failed for {name}: {e}"))?;
125 - Ok(response
126 - .iter()
127 - .map(|mx| mx.exchange().to_string().trim_end_matches('.').to_string())
135 + Ok(rdata(&response)
136 + .filter_map(|d| match d {
137 + RData::MX(mx) => Some(trim_root(&mx.exchange.to_string())),
138 + _ => None,
139 + })
128 140 .collect())
129 141 }
130 142
@@ -133,7 +145,22 @@ async fn resolve_txt(resolver: &TokioResolver, name: &str) -> Result<Vec<String>
133 145 .txt_lookup(name)
134 146 .await
135 147 .map_err(|e| format!("TXT lookup failed for {name}: {e}"))?;
136 - Ok(response.iter().map(|txt| txt.to_string()).collect())
148 + Ok(rdata(&response)
149 + .filter_map(|d| match d {
150 + RData::TXT(txt) => Some(txt.to_string()),
151 + _ => None,
152 + })
153 + .collect())
154 + }
155 +
156 + /// Answer-section rdata for a lookup. Typed lookups return a plain `Lookup` as of
157 + /// hickory 0.26, so every caller filters the answers down to the variant it asked for.
158 + fn rdata(response: &hickory_resolver::lookup::Lookup) -> impl Iterator<Item = &RData> {
159 + response.answers().iter().map(|record| &record.data)
160 + }
161 +
162 + fn trim_root(name: &str) -> String {
163 + name.trim_end_matches('.').to_string()
137 164 }
138 165
139 166 #[cfg(test)]