Update examples with modernized code
This commit is contained in:
@@ -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(_) => {}
|
||||
|
||||
Reference in New Issue
Block a user