Skip to content

Commit

Permalink
feat: add use of command line args
Browse files Browse the repository at this point in the history
Signed-off-by: nabil salah <[email protected]>
  • Loading branch information
Nabil-Salah committed Dec 23, 2024
1 parent fb195e7 commit ca76b3f
Show file tree
Hide file tree
Showing 5 changed files with 278 additions and 10 deletions.
230 changes: 230 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2021"

[dependencies]
clap = { version = "4.5.23", features = ["derive"] }

[profile.release]
target = "x86_64-unknown-linux-musl"
target = "x86_64-unknown-linux-musl"
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,19 @@ A simple and efficient DNS server implemented in Rust, designed to handle DNS qu
cargo build
```

### Command Line Options
This is the result of running hermes -h
```bash
A simple DNS server application

Usage: dnsserver-nabil [OPTIONS]

Options:
-p, --port <PORT> Port to bind the UDP socket [default: 2053]
-f, --forward-ip <FORWARD_IP> forward replies to specified dns server
-h, --help Print help
-V, --version Print version
```
### Running the Server

To run the DNS server, use the following command:
Expand Down
21 changes: 15 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,18 @@ use {
dns_question::DnsQuestion, query_types::QueryType,
};

fn recursive_lookup(qname: &str, qtype: QueryType) -> Result<DnsPacket, io::Error> {
// For now we're always starting with *a.root-servers.net*.
let mut ns = "198.41.0.4".parse::<Ipv4Addr>().unwrap();
fn recursive_lookup(
qname: &str,
qtype: QueryType,
root_ip: &Option<String>,
) -> Result<DnsPacket, io::Error> {
// For now we're always starting with *a.root-servers.net* if no forwarding ip specified.
let mut ns = match root_ip {
Some(ip) => ip,
None => "198.41.0.4",
}
.parse::<Ipv4Addr>()
.unwrap();

loop {
println!("attempting lookup of {:?} {} with ns {}", qtype, qname, ns);
Expand Down Expand Up @@ -44,7 +53,7 @@ fn recursive_lookup(qname: &str, qtype: QueryType) -> Result<DnsPacket, io::Erro
None => return Ok(response),
};

let recursive_response = recursive_lookup(&new_ns_name, QueryType::A)?;
let recursive_response = recursive_lookup(&new_ns_name, QueryType::A, root_ip)?;

if let Some(new_ns) = recursive_response.get_random_a() {
ns = new_ns;
Expand Down Expand Up @@ -80,7 +89,7 @@ fn lookup(qname: &str, qtype: QueryType, server: (Ipv4Addr, u16)) -> Result<DnsP
/// function handles an incoming DNS query from a UDP socket
/// and formulates an appropriate DNS response,
/// either answering directly or using recursive resolution to obtain the necessary data
pub fn handle_query(socket: &UdpSocket) -> Result<(), io::Error> {
pub fn handle_query(socket: &UdpSocket, root_ip: &Option<String>) -> Result<(), io::Error> {
let mut req_buffer = BytePacketBuffer::new();

let (_, src) = socket.recv_from(&mut req_buffer.buf)?;
Expand All @@ -95,7 +104,7 @@ pub fn handle_query(socket: &UdpSocket) -> Result<(), io::Error> {

if let Some(question) = request.questions.pop() {
println!("Received query: {:?}", question);
if let Ok(result) = recursive_lookup(&question.name, question.qtype) {
if let Ok(result) = recursive_lookup(&question.name, question.qtype, root_ip) {
packet.questions.push(question.clone());
packet.header.rescode = result.header.rescode;

Expand Down
21 changes: 18 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
use clap::Parser;
use std::{io, net::UdpSocket};

#[derive(Parser)]
#[command(name = "DnsServerApp")]
#[command(version = "1.0")]
#[command(about = "A simple DNS server application", long_about = None)]
struct Args {
/// Port to bind the UDP socket
#[arg(short, long, default_value_t = 2053)]
port: u16,
/// forward replies to specified dns server
#[arg(short, long, default_value = None)]
forward_ip: Option<String>,
}

fn main() -> Result<(), io::Error> {
// Bind an UDP socket on port 2053
let socket = UdpSocket::bind(("0.0.0.0", 2053))?;
let args = Args::parse();
// Bind an UDP socket on port
let socket = UdpSocket::bind(("0.0.0.0", args.port))?;

// For now, queries are handled sequentially, so an infinite loop for servicing
// requests is initiated.
loop {
match dnsserver_nabil::handle_query(&socket) {
match dnsserver_nabil::handle_query(&socket, &args.forward_ip) {
Ok(_) => {}
Err(e) => eprintln!("An error occurred: {}", e),
}
Expand Down

0 comments on commit ca76b3f

Please sign in to comment.