cloudflare-ddns-service/src/network.rs
Jan Christian Grünhage 5f25f85a5e chore: fork and rename
I'm forking this, with the following changes:
 - daemon instead of CLI tool run via cron
 - mandatory config file
 - use cloudflare crate instead of home grown API client
 - IPv6 support
 - CNPLv6+ licensed instead of MIT licensed
2021-05-23 15:33:28 +02:00

120 lines
2.9 KiB
Rust

use std::net::{Ipv4Addr, Ipv6Addr};
use anyhow::{Context, Result};
use cloudflare::{
endpoints::{
dns::{
DnsContent, ListDnsRecords, ListDnsRecordsParams, UpdateDnsRecord,
UpdateDnsRecordParams,
},
zone::{ListZones, ListZonesParams},
},
framework::async_api::Client as CfClient,
};
use reqwest::Client as ReqwClient;
pub const A_RECORD: DnsContent = DnsContent::A {
content: Ipv4Addr::UNSPECIFIED,
};
pub const AAAA_RECORD: DnsContent = DnsContent::AAAA {
content: Ipv6Addr::UNSPECIFIED,
};
pub async fn get_current_ipv4(client: &mut ReqwClient) -> Result<Ipv4Addr> {
Ok(client
.get("https://ipv4.icanhazip.com")
.send()
.await?
.text()
.await?
.trim()
.parse()?)
}
pub async fn get_current_ipv6(client: &mut ReqwClient) -> Result<Ipv6Addr> {
Ok(client
.get("https://ipv6.icanhazip.com")
.send()
.await?
.text()
.await?
.trim()
.parse()?)
}
pub async fn get_zone(domain: String, cf_client: &mut CfClient) -> Result<String> {
Ok(cf_client
.request_handle(&ListZones {
params: ListZonesParams {
name: Some(domain),
status: None,
page: None,
per_page: None,
order: None,
direction: None,
search_match: None,
},
})
.await?
.result[0]
.id
.clone())
}
pub async fn get_record(
zone_identifier: &str,
domain: String,
r#type: DnsContent,
cf_client: &mut CfClient,
) -> Result<String> {
Ok(cf_client
.request_handle(&ListDnsRecords {
zone_identifier,
params: ListDnsRecordsParams {
record_type: None,
name: Some(domain),
page: None,
per_page: None,
order: None,
direction: None,
search_match: None,
},
})
.await
.context("Couldn't fetch record")?
.result
.iter()
.find(|record| {
if std::mem::discriminant(&record.content) == std::mem::discriminant(&r#type) {
true
} else {
false
}
})
.context("No matching record found")?
.id
.clone())
}
pub async fn update_record(
zone_identifier: &str,
identifier: &str,
name: &str,
content: DnsContent,
cf_client: &mut CfClient,
) -> Result<()> {
cf_client
.request_handle(&UpdateDnsRecord {
zone_identifier,
identifier,
params: UpdateDnsRecordParams {
ttl: None,
proxied: Some(false),
name,
content,
},
})
.await?;
Ok(())
}