main.rs 1.44 KB
Newer Older
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
#![feature(proc_macro_hygiene, decl_macro)]
use std::str::FromStr;

#[macro_use] extern crate rocket;
use rocket::State;
use rocket_contrib::json::Json;

use trust_dns_client::client::{Client, SyncClient};
use trust_dns_client::tcp::TcpClientConnection;
use trust_dns_client::op::DnsResponse;
use trust_dns_client::rr::{DNSClass, Name, Record, RecordType};

mod types;
mod config;


#[get("/zones/<zone>/records")]
fn zone_records(client: State<SyncClient<TcpClientConnection>>, zone: String) -> Json<Vec<types::dns::Record>> {
    // TODO: Implement FromParam for Name
    let name = Name::from_str(&zone).unwrap();

22
    let response: DnsResponse = client.query(&name, DNSClass::IN, RecordType::AXFR).unwrap();
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
23
    let answers: &[Record] = response.answers();
24 25 26 27 28 29 30 31 32
    let mut records: Vec<_> = answers.to_vec().into_iter()
        .map(|record| types::dns::Record::from(record))
        .filter(|record| match record.rdata {
            types::dns::RData::NULL { .. } | types::dns::RData::DNSSEC(_) => false,
            _ => true,
        }).collect();

    // AXFR response ends with SOA, we remove it so it is not doubled in the response.
    records.pop();
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
33 34 35 36 37 38 39 40 41 42 43 44 45 46

    Json(records)
}

fn main() {
    let app_config = config::load("config.toml".into());

    let conn = TcpClientConnection::new(app_config.dns_server.address).unwrap();
    let client = SyncClient::new(conn);

    rocket::ignite()
        .manage(client)
        .mount("/api/v1", routes![zone_records]).launch();
}