Code for parsing headers added.
This commit is contained in:
96
src/main.rs
Normal file
96
src/main.rs
Normal file
@ -0,0 +1,96 @@
|
||||
use flume::{Receiver, Sender};
|
||||
use std::net::UdpSocket;
|
||||
use std::thread::{self, JoinHandle};
|
||||
use std::convert::TryInto;
|
||||
|
||||
mod proto;
|
||||
use proto::{DNSHeader, DNSOpCode, DNSRCode};
|
||||
|
||||
|
||||
fn listen() -> (JoinHandle<()>, Sender<Vec<u8>>, Receiver<Vec<u8>>) {
|
||||
let (tx, rx) = flume::unbounded();
|
||||
|
||||
let tx_clone = tx.clone();
|
||||
let rx_clone = rx.clone();
|
||||
|
||||
(
|
||||
thread::spawn(move || {
|
||||
let socket = UdpSocket::bind("127.0.0.1:13337").unwrap();
|
||||
|
||||
let mut buf = [0; 512];
|
||||
|
||||
loop {
|
||||
let (len, _src) = socket.recv_from(&mut buf).unwrap();
|
||||
|
||||
let buf = &mut buf[..len];
|
||||
tx.send(Vec::from(buf)).unwrap();
|
||||
}
|
||||
}),
|
||||
tx_clone,
|
||||
rx_clone,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
const QR_MASK:u16 = 0x0001;
|
||||
const OPCODE_MASK:u16 = 0x000e;
|
||||
const AA_MASK:u16 = 0x0020;
|
||||
const TC_MASK:u16 = 0x0040;
|
||||
const RD_MASK:u16 = 0x0080;
|
||||
const RA_MASK:u16 = 0x0100;
|
||||
const AD_MASK:u16 = 0x0400;
|
||||
const CD_MASK:u16 = 0x0800;
|
||||
const RCODE_MASK:u16 = 0xf000;
|
||||
|
||||
const OPCODE_OFFSET:u16 = 1;
|
||||
const RCODE_OFFSET:u16 = 11;
|
||||
|
||||
fn main() {
|
||||
let (thread_udp, _thread_udp_tx, thread_udp_rx) = listen();
|
||||
|
||||
for msg in thread_udp_rx.iter() {
|
||||
println!("{:?}", msg);
|
||||
|
||||
// TODO: check for enough data in msg
|
||||
|
||||
let id = u16::from_be_bytes((&msg[..2]).try_into().unwrap());
|
||||
|
||||
let flags = u16::from_be_bytes((&msg[2..4]).try_into().unwrap());
|
||||
let qr = (flags & QR_MASK) != 0;
|
||||
let opcode:DNSOpCode = DNSOpCode::from((flags & OPCODE_MASK) >> OPCODE_OFFSET);
|
||||
let authoritative_answer = (flags & AA_MASK) != 0;
|
||||
let truncated = (flags & TC_MASK) != 0;
|
||||
let recursion_desired= (flags & RD_MASK) != 0;
|
||||
let recursion_available = (flags & RA_MASK) != 0;
|
||||
let authentic_data = (flags & AD_MASK) != 0;
|
||||
let checking_disabled = (flags & CD_MASK) != 0;
|
||||
let response_code: DNSRCode = DNSRCode::from((flags & RCODE_MASK) >> RCODE_OFFSET);
|
||||
|
||||
let qd_zo_count = u16::from_be_bytes((&msg[4..6]).try_into().unwrap());
|
||||
let an_pr_count = u16::from_be_bytes((&msg[6..8]).try_into().unwrap());
|
||||
let ns_up_count = u16::from_be_bytes((&msg[8..10]).try_into().unwrap());
|
||||
let ar_count = u16::from_be_bytes((&msg[10..12]).try_into().unwrap());
|
||||
|
||||
let hdr_struct = DNSHeader {
|
||||
id,
|
||||
qr,
|
||||
opcode,
|
||||
authoritative_answer,
|
||||
truncated,
|
||||
recursion_desired,
|
||||
recursion_available,
|
||||
authentic_data,
|
||||
checking_disabled,
|
||||
response_code,
|
||||
qd_zo_count,
|
||||
an_pr_count,
|
||||
ns_up_count,
|
||||
ar_count,
|
||||
};
|
||||
|
||||
dbg!(hdr_struct);
|
||||
|
||||
}
|
||||
|
||||
let _ = thread_udp.join();
|
||||
}
|
84
src/proto.rs
Normal file
84
src/proto.rs
Normal file
@ -0,0 +1,84 @@
|
||||
#[derive(Debug)]
|
||||
pub enum DNSOpCode {
|
||||
QUERY = 0,
|
||||
IQUERY = 1, // obsolete
|
||||
STATUS = 2,
|
||||
NOTIFY = 4,
|
||||
UPDATE = 5,
|
||||
}
|
||||
|
||||
impl From<u16> for DNSOpCode {
|
||||
fn from(val: u16) -> Self {
|
||||
match val {
|
||||
0 => DNSOpCode::QUERY,
|
||||
1 => DNSOpCode::IQUERY,
|
||||
2 => DNSOpCode::STATUS,
|
||||
4 => DNSOpCode::NOTIFY,
|
||||
5 => DNSOpCode::UPDATE,
|
||||
_ => panic!("KACKE"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: FIXME: TECHNISCHE SCHULD (alle pubs weg und gucken wie es richtig geht)
|
||||
#[derive(Debug)]
|
||||
pub enum DNSRCode {
|
||||
NOERROR = 0,
|
||||
FORMERR = 1,
|
||||
SERVFAIL = 2,
|
||||
NXDOMAIN = 3,
|
||||
NOTIMP = 4,
|
||||
REFUSED = 5,
|
||||
XYDOMAIN = 6,
|
||||
XYRRSET = 7,
|
||||
NXRRSET = 8,
|
||||
NOTAUTH = 9,
|
||||
NOTINZONE = 10,
|
||||
}
|
||||
|
||||
impl From<u16> for DNSRCode {
|
||||
fn from(val: u16) -> Self {
|
||||
match val {
|
||||
0 => DNSRCode::NOERROR,
|
||||
1 => DNSRCode::FORMERR,
|
||||
2 => DNSRCode::SERVFAIL,
|
||||
3 => DNSRCode::NXDOMAIN,
|
||||
4 => DNSRCode::NOTIMP,
|
||||
5 => DNSRCode::REFUSED,
|
||||
6 => DNSRCode::XYDOMAIN,
|
||||
7 => DNSRCode::XYRRSET,
|
||||
8 => DNSRCode::NXRRSET,
|
||||
9 => DNSRCode::NOTAUTH,
|
||||
10 => DNSRCode::NOTINZONE,
|
||||
_ => panic!("KACKE"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DNSHeader {
|
||||
/// used by the requester to match up replies to outstanding queries
|
||||
pub id: u16,
|
||||
/// specifies whether this message is a query (false), or a response (true)
|
||||
pub qr: bool,
|
||||
pub opcode: DNSOpCode,
|
||||
pub authoritative_answer: bool,
|
||||
pub truncated: bool,
|
||||
pub recursion_desired: bool,
|
||||
pub recursion_available: bool,
|
||||
pub authentic_data: bool,
|
||||
pub checking_disabled: bool,
|
||||
pub response_code: DNSRCode,
|
||||
pub qd_zo_count: u16,
|
||||
pub an_pr_count: u16,
|
||||
pub ns_up_count: u16,
|
||||
pub ar_count: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DNSQuery {
|
||||
pub hdr: DNSHeader,
|
||||
pub name: String,
|
||||
pub qclass: u16,
|
||||
pub qtype: u16,
|
||||
}
|
Reference in New Issue
Block a user