Skip to content

Commit 5ee8f61

Browse files
implement a dns server
1 parent b49136c commit 5ee8f61

File tree

1 file changed

+88
-24
lines changed

1 file changed

+88
-24
lines changed

src/main.rs

Lines changed: 88 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -720,18 +720,14 @@ impl DnsPacket {
720720
}
721721
}
722722

723-
fn main() -> Result<()> {
724-
// perform a query for youtube.com
725-
let q_name = "youtube.com";
726-
let q_type = QueryType::A;
727-
728-
//use youtube public dns server
723+
// Add lookup method to lookup DNS records
724+
fn lookup(query_name: &str, query_type: QueryType) -> Result<DnsPacket> {
725+
//forward query to public dns
729726
let server = ("8.8.8.8", 53);
730727

731728
// bind a UDP socket to arbitrary port
732729
let socket = UdpSocket::bind(("0.0.0.0", 42340))?;
733730

734-
735731
// Build our query packet. It's important that we remember to set the
736732
// `recursion_desired` flag. As noted earlier, the packet id is arbitrary.
737733
let mut packet = DnsPacket::new();
@@ -740,37 +736,105 @@ fn main() -> Result<()> {
740736
packet.header.recursion_desired = true;
741737
packet
742738
.questions
743-
.push(DnsQuestion::new(q_name.to_string(), q_type));
744-
739+
.push(DnsQuestion::new(query_name.to_string(), query_type));
745740

746741
// Use our new write method to write the packet to a buffer...
747742
let mut req_buffer = BytePacketBuffer::new();
748743
packet.write(&mut req_buffer)?;
749744

750-
// ...and send it off to the server using our socket:
751-
socket.send_to(&req_buffer.buf[0..req_buffer.pos], server)?;
745+
// ...and send it off to the server using our socket:
746+
socket.send_to(&req_buffer.buf[0..req_buffer.pos], server)?;
752747

753748
// To prepare for receiving the response, we'll create a new `BytePacketBuffer`,
754749
// and ask the socket to write the response directly into our buffer.
755750
let mut res_buffer = BytePacketBuffer::new();
756751
socket.recv_from(&mut res_buffer.buf)?;
757752

758-
//`DnsPacket::from_buffer()` is used to parse the response and print it
759-
let packet = DnsPacket::from_buffer(&mut res_buffer)?;
760-
println!("{:#?}", packet.header);
753+
//`DnsPacket::from_buffer()` is used to parse the response
754+
DnsPacket::from_buffer(&mut res_buffer)
761755

762-
for q in packet.questions {
763-
println!("{:#?}", q);
764-
}
765-
for rec in packet.answers {
766-
println!("{:#?}", rec);
767-
}
768-
for rec in packet.authorities {
769-
println!("{:#?}", rec);
756+
}
757+
/// Handle a single incoming packet
758+
fn handle_query(socket: &UdpSocket) -> Result<()> {
759+
// With a socket ready, we can go ahead and read a packet. This will
760+
// block until one is received.
761+
let mut req_buffer = BytePacketBuffer::new();
762+
763+
// The `recv_from` function will write the data into the provided buffer,
764+
// and return the length of the data read as well as the source address.
765+
// We're not interested in the length, but we need to keep track of the
766+
// source in order to send our reply later on.
767+
let (_, src) = socket.recv_from(&mut req_buffer.buf)?;
768+
769+
// Next, `DnsPacket::from_buffer` is used to parse the raw bytes into
770+
// a `DnsPacket`.
771+
let mut request = DnsPacket::from_buffer(&mut req_buffer)?;
772+
773+
// Create and initialize the response packet
774+
let mut packet = DnsPacket::new();
775+
packet.header.id = request.header.id;
776+
packet.header.recursion_desired = true;
777+
packet.header.recursion_available = true;
778+
packet.header.response = true;
779+
780+
// In the normal case, exactly one question is present
781+
if let Some(question) = request.questions.pop() {
782+
println!("Received query: {:?}", question);
783+
784+
// Since all is set up and as expected, the query can be forwarded to the
785+
// target server. There's always the possibility that the query will
786+
// fail, in which case the `SERVFAIL` response code is set to indicate
787+
// as much to the client. If rather everything goes as planned, the
788+
// question and response records as copied into our response packet.
789+
if let Ok(result) = lookup(&question.name, question.question_type) {
790+
packet.questions.push(question);
791+
packet.header.rescode = result.header.rescode;
792+
793+
for rec in result.answers {
794+
println!("Answer: {:?}", rec);
795+
packet.answers.push(rec);
796+
}
797+
for rec in result.authorities {
798+
println!("Authority: {:?}", rec);
799+
packet.authorities.push(rec);
800+
}
801+
for rec in result.resources {
802+
println!("Resource: {:?}", rec);
803+
packet.resources.push(rec);
804+
}
805+
} else {
806+
packet.header.rescode = ResultCode::SERVFAIL;
807+
}
770808
}
771-
for rec in packet.resources {
772-
println!("{:#?}", rec);
809+
// Being mindful of how unreliable input data from arbitrary senders can be, we
810+
// need make sure that a question is actually present. If not, we return `FORMERR`
811+
// to indicate that the sender made something wrong.
812+
else {
813+
packet.header.rescode = ResultCode::FORMERR;
773814
}
774815

816+
// encode our response and send it back
817+
let mut res_buffer = BytePacketBuffer::new();
818+
packet.write(&mut res_buffer)?;
819+
820+
let len = res_buffer.pos();
821+
let data = res_buffer.get_range(0, len)?;
822+
823+
socket.send_to(data, src)?;
824+
775825
Ok(())
776826
}
827+
828+
fn main() -> Result<()> {
829+
// Bind an UDP socket on port 2053
830+
let socket = UdpSocket::bind(("0.0.0.0", 2053))?;
831+
832+
// For now, queries are handled sequentially, so an infinite loop for servicing
833+
// requests is initiated.
834+
loop {
835+
match handle_query(&socket) {
836+
Ok(_) => {},
837+
Err(e) => eprintln!("An error occurred: {}", e),
838+
}
839+
}
840+
}

0 commit comments

Comments
 (0)