using --ipv6 cli argument

This commit is contained in:
2025-06-08 12:30:44 +02:00
parent 98de3116ac
commit ae9e7e43c2
3 changed files with 164 additions and 20 deletions

127
Cargo.lock generated
View File

@@ -17,6 +17,56 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]]
name = "anstream"
version = "0.6.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
[[package]]
name = "anstyle-parse"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882"
dependencies = [
"anstyle",
"once_cell_polyfill",
"windows-sys 0.59.0",
]
[[package]]
name = "atomic-waker"
version = "1.1.2"
@@ -89,6 +139,52 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "clap"
version = "4.5.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]]
name = "colorchoice"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
[[package]]
name = "core-foundation"
version = "0.9.4"
@@ -291,10 +387,17 @@ version = "0.15.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hetzner_ddns"
version = "0.1.0"
dependencies = [
"clap",
"dotenv",
"reqwest",
"serde",
@@ -553,6 +656,12 @@ dependencies = [
"serde",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itoa"
version = "1.0.15"
@@ -663,6 +772,12 @@ version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "once_cell_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
[[package]]
name = "openssl"
version = "0.10.73"
@@ -1104,6 +1219,12 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "subtle"
version = "2.6.1"
@@ -1367,6 +1488,12 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "vcpkg"
version = "0.2.15"

View File

@@ -4,7 +4,8 @@ version = "0.1.0"
edition = "2021"
[dependencies]
clap = { version = "4.5", features = ["derive"] }
dotenv = "0.15"
reqwest = { version = "0.12", features = ["json", "blocking", "rustls-tls"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
dotenv = "0.15"

View File

@@ -2,6 +2,7 @@ use std::env;
use reqwest::blocking::Client;
use serde::{Deserialize, Serialize};
use dotenv::dotenv;
use clap::Parser;
use dotenv::Error as DotenvError;
#[derive(Deserialize)]
@@ -31,7 +32,18 @@ struct RecordList {
records: Vec<Record>,
}
#[derive(Parser, Debug)]
#[command(name = "hetzner-ddns", version, about = "Dynamic DNS updater for Hetzner")]
struct Cli {
/// Update the AAAA (IPv6) record as well
#[arg(long)]
ipv6: bool,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = Cli::parse();
let update_ipv6 = args.ipv6;
match dotenv() {
Ok(_) => {} // .env loaded
Err(DotenvError::Io(ref e)) if e.kind() == std::io::ErrorKind::NotFound => {
@@ -100,31 +112,35 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("⚠️ A record not found.");
}
// --- IPv6 (AAAA) Record ---
if let Some(ip6) = ip6 {
if let Some(record6) = records.records.iter().find(|r| r.name == record_name && r.record_type == "AAAA") {
if record6.value != ip6 {
println!("🔄 Updating AAAA record from {} to {}", record6.value, ip6);
let updated6 = Record {
value: ip6.clone(),
ttl: Some(60),
..record6.to_owned()
};
// --- IPv6 (AAAA) Record ---
if update_ipv6 {
if let Some(ip6) = ip6 {
if let Some(record6) = records.records.iter().find(|r| r.name == record_name && r.record_type == "AAAA") {
if record6.value != ip6 {
println!("🔄 Updating AAAA record from {} to {}", record6.value, ip6);
let updated6 = Record {
value: ip6.clone(),
ttl: Some(60),
..record6.to_owned()
};
client.put(format!("https://dns.hetzner.com/api/v1/records/{}", record6.id))
.header("Auth-API-Token", &api_token)
.header("Content-Type", "application/json")
.json(&updated6)
.send()?;
println!("✅ AAAA record updated.");
client.put(format!("https://dns.hetzner.com/api/v1/records/{}", record6.id))
.header("Auth-API-Token", &api_token)
.header("Content-Type", "application/json")
.json(&updated6)
.send()?;
println!("✅ AAAA record updated.");
} else {
println!("✅ AAAA record already up to date: {}", ip6);
}
} else {
println!(" AAAA record already up to date: {}", ip6);
println!("⚠️ AAAA record not found.");
}
} else {
println!(" AAAA record not found.");
println!(" No public IPv6 address found. Skipping AAAA update.");
}
} else {
println!(" No public IPv6 address found. Skipping AAAA update.");
println!(" Skipping AAAA update (use --ipv6 to enable).");
}
Ok(())