~kf5jwc/dns-server-rs

6aeb1246ca37e1542d695ba1729b2d67f7e92b5b — Kyle Jones 6 months ago c0b118a
Make the stub resolver more useful from cmdline

- Convert to using an argument parser
- Allow specifying query server and rtype
- Allow specifying a domain
1 files changed, 37 insertions(+), 12 deletions(-)

M src/bin/stub_resolver.rs
M src/bin/stub_resolver.rs => src/bin/stub_resolver.rs +37 -12
@@ 1,30 1,53 @@
extern crate log;
extern crate env_logger;
extern crate rand;
extern crate structopt;
extern crate dns_server;

use std::net::IpAddr;
use std::net::UdpSocket;
use log::{info, debug};
use rand::Rng;
use structopt::StructOpt;
use dns_server::{
    BytePacketBuffer,
    DnsPacket,
    DnsQuestion,
    QueryType,
};
use QueryType::A as QTypeA;

#[derive(Debug, StructOpt)]
#[structopt()]
struct Args {
    #[structopt()]
    domains: Vec<String>,
    #[structopt(short, parse(try_from_str), default_value="A")]
    record_type: QueryType,
    #[structopt(short, parse(try_from_str), default_value="192.168.1.1")]
    server: IpAddr,
    #[structopt(short, parse(try_from_str), default_value="53")]
    port: u16,
}

fn main() {
    env_logger::init();
    let args = Args::from_args();

    let server = ("10.0.0.1", 53);
    let socket = UdpSocket::bind(("0.0.0.0", 43210)).expect("UDP socket server");
    let packet = make_dns_packet("yahoo.com", QTypeA);
    info!("Generating query packet");
    let packet = make_dns_query_packet(args.domains, args.record_type);
    let req_buffer: BytePacketBuffer = packet.into();

    info!("Starting resolver");
    let server = (args.server, args.port);
    let socket = UdpSocket::bind(("0.0.0.0", 43120)).expect("Opening upstream request socket");
    info!("Sending request to server");
    socket.send_to(&req_buffer.buf[0..req_buffer.pos], server).expect("Sending message to upstream server");

    info!("Awaiting response from server");
    let mut res_buffer = BytePacketBuffer::default();
    socket.recv_from(&mut res_buffer.buf).unwrap();

    info!("Parsing response");
    let res_packet: DnsPacket = res_buffer.into();
    println!("{:?}", res_packet.header);



@@ 42,18 65,20 @@ fn main() {
    }
}

fn make_dns_packet(qname: &str, qtype: QueryType) -> DnsPacket {
fn make_dns_query_packet(qnames: Vec<String>, qtype: QueryType) -> DnsPacket {
    let mut rng = rand::thread_rng();
    let mut packet = DnsPacket::default();
    packet.header.id = rng.gen();
    packet.header.questions = 1;
    packet.header.questions = qnames.len() as u16;
    packet.header.recursion_desired = true;
    packet.questions.push({
        DnsQuestion{
            name: qname.to_string(),
            qtype: qtype,
        }
    });
    for qname in qnames {
        packet.questions.push({
            DnsQuestion{
                name: qname,
                qtype: qtype,
            }
        });
    }

    return packet;
}