Open chenxiaolong opened 2 years ago
Does compare and swap facilitate what you want? https://docs.rs/trust-dns-client/latest/trust_dns_client/client/trait.Client.html#method.compare_and_swap
Or do you want to blindly delete all records and add a new set? We could add a replace
method that does what you want.
Thank you, I had overlooked that method. Blind-replace-all semantics is indeed what I'm after. I'll play around and see if query
+ compare_and_swap
can do the trick.
(Looking at the source for compare_and_swap
, the low-level trust_dns_client::op::Message
API seems pretty straight-forward as well. Seems like I can go that route if needed.)
I got this working using the low level Message
API and it lets me handle both A and AAAA at the same time. I'm not sure if it's worth having a high level wrapper for this--I'm perfectly happy with just using Message
.
fn replace_addrs_message(
zone_origin: Name,
name: Name,
ttl: u32,
addrs: &[IpAddr],
) -> Message {
// trust_dns_client::client::AsyncClient::MAX_PAYLOAD_LEN is not public
const MAX_PAYLOAD_LEN: u16 = 1232;
let mut zone = Query::new();
zone.set_name(zone_origin)
.set_query_class(DNSClass::IN)
.set_query_type(RecordType::SOA);
let mut message = Message::new();
message
.set_id(rand::random())
.set_message_type(MessageType::Query)
.set_op_code(OpCode::Update)
.set_recursion_desired(false);
message.add_zone(zone);
for rtype in [RecordType::A, RecordType::AAAA] {
let mut record = Record::with(name.clone(), rtype, 0);
record.set_dns_class(DNSClass::ANY);
message.add_update(record);
}
for addr in addrs {
let rdata = match addr {
IpAddr::V4(ip) => RData::A(*ip),
IpAddr::V6(ip) => RData::AAAA(*ip),
};
message.add_update(Record::from_rdata(name.clone(), ttl, rdata));
}
let edns = message.edns_mut();
edns.set_max_payload(MAX_PAYLOAD_LEN);
edns.set_version(0);
message
}
As I understand it, with dynamic DNS, to atomically replace all A records for a host and add a new one, both the deletion and creation need to be done in the same request (assuming the server supports atomic updates). With
nsupdate
, I'd do something like this:Looking at a packet capture, that gives me a single request (1 packet) with two entries in the update section:
I was able to mostly implement this using trust-dns thanks to the recent TSIG support, but it seems that each call to eg.
SyncClient::delete_rrset
/create
/append
sends a new request. Is there any API for sending multiple updates in a single request?Thank you!