diff --git a/.gitignore b/.gitignore index ea8c4bf..e7722c8 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /target +.env +*.sqlite diff --git a/Cargo.toml b/Cargo.toml index 95d3087..bd4bbb0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,3 @@ edition = "2021" diesel = { version = "2.1.4", features = ["sqlite"] } dotenvy = "0.15" tokio = {version = "1.36.0", features = ["full"]} - diff --git a/diesel.toml b/diesel.toml new file mode 100644 index 0000000..c028f4a --- /dev/null +++ b/diesel.toml @@ -0,0 +1,9 @@ +# For documentation on how to configure this file, +# see https://diesel.rs/guides/configuring-diesel-cli + +[print_schema] +file = "src/schema.rs" +custom_type_derives = ["diesel::query_builder::QueryId"] + +[migrations_directory] +dir = "migrations" diff --git a/migrations/.keep b/migrations/.keep new file mode 100644 index 0000000..e69de29 diff --git a/src/main.rs b/src/main.rs index 73a0e7a..b6a0211 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,8 @@ use parser::FromBytes; use structs::Message; use tokio::net::UdpSocket; +use crate::structs::{Class, Type, RR}; + mod errors; mod parser; mod structs; @@ -11,8 +13,24 @@ mod worker; const MAX_DATAGRAM_SIZE: usize = 40_96; -async fn create_query(message: Message) { - println!("{:?}", message); +async fn create_query(message: Message) -> Message { + let mut response = message.clone(); + let ip = String::from("93.184.216.34"); + let rr = RR { + name: vec![String::from("example"),String::from("org")], + _type: Type::A, + class: Class::IN, + ttl: 4096, + rdlength: ip.len() as u16, + rdata: ip, + }; + + response.header.flags |= 0b1000010110000000; + response.header.ancount = 1; + response.header.arcount = 0; + response.answer = Some(rr); + + response } #[tokio::main] @@ -22,13 +40,19 @@ async fn main() -> Result<(), Box> { let socket = UdpSocket::bind(local_addr).await?; let mut data = vec![0u8; MAX_DATAGRAM_SIZE]; - loop { - let len = socket.recv(&mut data).await?; - match Message::from_bytes(&data[..len]) { - Ok(message) => { - tokio::spawn(async move { create_query(message).await }); - } - Err(err) => println!("{}", err), - }; - } + let (len,addr) = socket.recv_from(&mut data).await?; + match Message::from_bytes(&data[..len]) { + Ok(message) => { + tokio::spawn(async move { + let response = create_query(message).await; + println!("{:?}",response); + let vec = Message::to_bytes(&response); + let decoded = Message::from_bytes(vec.as_slice()); + println!("{:?}",decoded); + let _ = socket.send_to(vec.as_slice(),addr).await; + }); + } + Err(err) => println!("{}", err), + }; + loop {} } diff --git a/src/parser.rs b/src/parser.rs index ee35a14..1f94e0b 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,8 +1,8 @@ -use std::mem::size_of; +use std::{mem::size_of, vec}; use crate::{ errors::ParseError, - structs::{Class, Header, Message, Question, Type}, + structs::{Class, Header, Message, Question, Type, RR}, }; type Result = std::result::Result; @@ -29,11 +29,13 @@ impl TryFrom for Class { } } -// TODO: use Error instead of Option pub trait FromBytes { fn from_bytes(bytes: &[u8]) -> Result where Self: Sized; + fn to_bytes(s: &Self) -> Vec + where + Self: Sized; } impl FromBytes for Header { @@ -54,9 +56,21 @@ impl FromBytes for Header { }) } } + + fn to_bytes(header: &Self) -> Vec { + let mut result: [u8; size_of::
()] = [0; size_of::
()]; + + result[0..2].copy_from_slice(&u16::to_be_bytes(header.id)); + result[2..4].copy_from_slice(&u16::to_be_bytes(header.flags)); + result[4..6].copy_from_slice(&u16::to_be_bytes(header.qdcount)); + result[6..8].copy_from_slice(&u16::to_be_bytes(header.ancount)); + result[8..10].copy_from_slice(&u16::to_be_bytes(header.nscount)); + result[10..12].copy_from_slice(&u16::to_be_bytes(header.arcount)); + + result.to_vec() + } } -//HACK: lots of unsafe unwrap impl FromBytes for Question { fn from_bytes(bytes: &[u8]) -> Result { // 16 for length octet + zero length octet @@ -107,6 +121,45 @@ impl FromBytes for Question { } } } + + fn to_bytes(question: &Self) -> Vec { + let mut result: Vec = vec![]; + for label in &question.qname { + result.push(label.len() as u8); + result.extend(label.as_bytes()); + } + result.push(0); + result.extend(u16::to_be_bytes(question.qtype.to_owned() as u16)); + result.extend(u16::to_be_bytes(question.qclass.to_owned() as u16)); + result + } +} + +impl FromBytes for RR { + fn from_bytes(bytes: &[u8]) -> Result + where + Self: Sized, + { + todo!() + } + + fn to_bytes(rr: &Self) -> Vec { + let mut result = vec![]; + for label in &rr.name { + result.push(label.len() as u8); + result.extend(label.as_bytes()); + } + result.push(0); + result.extend(u16::to_be_bytes(rr._type.to_owned() as u16)); + result.extend(u16::to_be_bytes(rr.class.to_owned() as u16)); + result.extend(i32::to_be_bytes(rr.ttl.to_owned())); + result.extend(u16::to_be_bytes(4 as u16)); + result.push(93); + result.push(184); + result.push(216); + result.push(34); + result + } } impl FromBytes for Message { @@ -121,4 +174,20 @@ impl FromBytes for Message { additional: None, }) } + + fn to_bytes(message: &Self) -> Vec { + let mut result = vec![]; + result.extend(Header::to_bytes(&message.header)); + result.extend(Question::to_bytes(&message.question)); + if message.answer.is_some() { + result.extend(RR::to_bytes(&message.answer.clone().unwrap())); + } + if message.authority.is_some() { + result.extend(RR::to_bytes(&message.authority.clone().unwrap())); + } + if message.additional.is_some() { + result.extend(RR::to_bytes(&message.additional.clone().unwrap())); + } + result + } } diff --git a/src/structs.rs b/src/structs.rs index 320bd86..489c373 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -1,24 +1,23 @@ - #[repr(u16)] -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Type { A = 1, } #[repr(u16)] -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Class { IN = 1, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Question { pub qname: Vec, // TODO: not padded pub qtype: Type, // NOTE: should be QTYPE, right now not really needed - pub qclass: Class, + pub qclass: Class, //NOTE: should be QCLASS, right now not really needed } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Header { pub id: u16, pub flags: u16, // |QR| Opcode |AA|TC|RD|RA| Z | RCODE | ; 1 | 4 | 1 | 1 | 1 | 1 | 3 | 4 @@ -28,7 +27,7 @@ pub struct Header { pub arcount: u16, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Message { pub header: Header, pub question: Question, @@ -37,14 +36,14 @@ pub struct Message { pub additional: Option, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct RR { - name: String, - t: u16, - class: u16, - ttl: u32, - rdlength: u16, - rdata: String, + pub name: Vec, + pub _type: Type, + pub class: Class, + pub ttl: i32, + pub rdlength: u16, + pub rdata: String, } #[derive(Debug)]