Update examples with modernized code

This commit is contained in:
Emil Hernvall
2020-06-18 01:47:09 +02:00
parent 31369696d9
commit f815075ae4
10 changed files with 708 additions and 627 deletions

View File

@@ -164,9 +164,7 @@ impl BytePacketBuffer {
}
fn write_qname(&mut self, qname: &str) -> Result<()> {
let split_str = qname.split('.').collect::<Vec<&str>>();
for label in split_str {
for label in qname.split('.') {
let len = label.len();
if len > 0x34 {
return Err("Single label exceeds 63 characters of length".into());
@@ -714,11 +712,17 @@ fn lookup(qname: &str, qtype: QueryType, server: (&str, u16)) -> Result<DnsPacke
}
fn main() -> Result<()> {
// Forward queries to Google's public DNS
let server = ("8.8.8.8", 53);
// Bind an UDP socket on port 2053
let socket = UdpSocket::bind(("0.0.0.0", 2053))?;
// For now, queries are handled sequentially, so an infinite loop for servicing
// requests is initiated.
loop {
// With a socket ready, we can go ahead and read a packet. This will
// block until one is received.
let mut req_buffer = BytePacketBuffer::new();
let (_, src) = match socket.recv_from(&mut req_buffer.buf) {
Ok(x) => x,
@@ -728,6 +732,16 @@ fn main() -> Result<()> {
}
};
// Here we use match to safely unwrap the `Result`. If everything's as expected,
// the raw bytes are simply returned, and if not it'll abort by restarting the
// loop and waiting for the next request. The `recv_from` function will write the
// data into the provided buffer, and return the length of the data read as well
// as the source address. We're not interested in the length, but we need to keep
// track of the source in order to send our reply later on.
// Next, `DnsPacket::from_buffer` is used to parse the raw bytes into
// a `DnsPacket`. It uses the same error handling idiom as the previous statement.
let request = match DnsPacket::from_buffer(&mut req_buffer) {
Ok(x) => x,
Err(e) => {
@@ -736,18 +750,29 @@ fn main() -> Result<()> {
}
};
// Create and initialize the response packet
let mut packet = DnsPacket::new();
packet.header.id = request.header.id;
packet.header.recursion_desired = true;
packet.header.recursion_available = true;
packet.header.response = true;
// Being mindful of how unreliable input data from arbitrary senders can be, we
// need make sure that a question is actually present. If not, we return `FORMERR`
// to indicate that the sender made something wrong.
if request.questions.is_empty() {
packet.header.rescode = ResultCode::FORMERR;
} else {
}
// Usually a question will be present, though.
else {
let question = &request.questions[0];
println!("Received query: {:?}", question);
// Since all is set up and as expected, the query can be forwarded to the target
// server. There's always the possibility that the query will fail, in which case
// the `SERVFAIL` response code is set to indicate as much to the client. If
// rather everything goes as planned, the question and response records as copied
// into our response packet.
if let Ok(result) = lookup(&question.name, question.qtype, server) {
packet.questions.push(question.clone());
packet.header.rescode = result.header.rescode;
@@ -769,6 +794,7 @@ fn main() -> Result<()> {
}
}
// The only thing remaining is to encode our response and send it off!
let mut res_buffer = BytePacketBuffer::new();
match packet.write(&mut res_buffer) {
Ok(_) => {}