Files
NLnetLabs-domain/examples/client.rs
T
Martin HoffmannandGitHub 5075e31f7c Refactor OPT options. (#193)
This PR refactors the existing support for OPT options. It does the
following things:

  o  Changes all option data types to ensure their wire format is at most
     65,535 octets long. This requires changing the signatures of some
     creator functions. Their naming scheme and signatures are also changed
     to follow the pattern established with record data.

  o  Renamed `UnknownOptData::from_octets` to `new` and return a result.

  o  Completely redesigns DNS cookie options, adding support for standard
     server cookies introduced in RFC 9018.

  o  Change the type of `ExtendedError`’s text to `Str<Octs>` and change the
     return type of `set_text` to `()`.

  o  Changed the type `TcpKeepalive`’s content to a newtype `IdleTimeout` to
     make it easier to convert to and from durations.

  o  Changes Padding to just contain the padding octets and drop
     `PaddingMode`. Instead, the methods on OptBuilder` should be used to
     add padding.

This is a breaking change.
2023-04-28 11:20:35 +02:00

103 lines
2.7 KiB
Rust

use std::net::UdpSocket;
use std::str::FromStr;
use domain::base::opt::AllOptData;
use domain::base::{
Dname, Message, MessageBuilder, Rtype, StaticCompressor, StreamTarget,
};
use domain::rdata::AllRecordData;
fn create_message() -> StreamTarget<Vec<u8>> {
// Create a message builder wrapping a compressor wrapping a stream
// target.
let mut msg = MessageBuilder::from_target(StaticCompressor::new(
StreamTarget::new_vec(),
))
.unwrap();
// Set the RD bit and a random ID in the header and proceed to
// the question section.
msg.header_mut().set_rd(true);
msg.header_mut().set_random_id();
let mut msg = msg.question();
// Add a hard-coded question and proceed to the answer section.
msg.push((
Dname::<Vec<u8>>::from_str("example.com.").unwrap(),
Rtype::A,
))
.unwrap();
// Skip to the additional section
let mut msg = msg.additional();
// Add an OPT record.
msg.opt(|opt| {
opt.set_udp_payload_size(4096);
Ok(())
})
.unwrap();
// Convert the builder into the actual message.
msg.finish().into_target()
}
fn main() {
// Bind a UDP socket to a kernel-provided port
let socket =
UdpSocket::bind("0.0.0.0:0").expect("couldn't bind to address");
let message = create_message();
let server: String = "127.0.0.1".to_string();
let port: u16 = 53;
// Send message off to the server using our socket
socket
.send_to(message.as_dgram_slice(), (server, port))
.unwrap();
// Create recv buffer
let mut buffer = vec![0; 1232];
// Recv in buffer
socket.recv_from(&mut buffer).unwrap();
// Parse and print the response
let response = match Message::from_octets(buffer) {
Ok(response) => Some(response),
Err(_) => None,
}
.unwrap();
for question in response.question() {
println!("{}", question.unwrap());
}
// Unpack and parse with all known record types
for record in response.answer().unwrap().limit_to::<AllRecordData<_, _>>()
{
println!("{}", record.unwrap());
}
for record in response
.authority()
.unwrap()
.limit_to::<AllRecordData<_, _>>()
{
println!("{}", record.unwrap());
}
// Display is only implemented for some OPTs at the time of writing
for option in response.opt().unwrap().opt().iter::<AllOptData<_, _>>() {
let opt = option.unwrap();
match opt {
AllOptData::Nsid(nsid) => println!("{}", nsid),
AllOptData::ExtendedError(extendederror) => {
println!("{}", extendederror)
}
_ => println!("NO OPT!"),
}
}
}