#![feature(proc_macro_hygiene, decl_macro)] #[macro_use] extern crate rocket; #[macro_use] extern crate rocket_contrib; #[macro_use] extern crate diesel; use rocket::State; use rocket::http::Status; use rocket_contrib::json::Json; use trust_dns_client::client::{Client, SyncClient}; use trust_dns_client::tcp::TcpClientConnection; use trust_dns_client::op::{DnsResponse, ResponseCode}; use trust_dns_client::rr::{DNSClass, Name, RecordType}; mod models; mod config; mod auth; mod schema; use models::errors::ErrorResponse; use auth::routes::*; #[database("db")] pub struct DbConn(diesel::SqliteConnection); #[get("/zones//records")] fn get_zone_records(client: State>, zone: String) -> Result>, ErrorResponse<()>> { // TODO: Implement FromParam for Name let name = Name::from_utf8(&zone).unwrap(); let response: DnsResponse = client.query(&name, DNSClass::IN, RecordType::AXFR).unwrap(); if response.response_code() != ResponseCode::NoError { return ErrorResponse::new( Status::NotFound, format!("zone {} could not be found", name.to_utf8()) ).err() } let answers = response.answers(); let mut records: Vec<_> = answers.to_vec().into_iter() .map(|record| models::dns::Record::from(record)) .filter(|record| match record.rdata { models::dns::RData::NULL { .. } | models::dns::RData::DNSSEC(_) => false, _ => true, }).collect(); // AXFR response ends with SOA, we remove it so it is not doubled in the response. records.pop(); Ok(Json(records)) } fn main() { let app_config = config::load("config.toml".into()); println!("{:#?}", app_config); let conn = TcpClientConnection::new(app_config.dns.server).unwrap(); let client = SyncClient::new(conn); rocket::ignite() .manage(client) .manage(app_config) .attach(DbConn::fairing()) .mount("/api/v1", routes![get_zone_records, create_auth_token, create_user]).launch(); }