Move parsing of udp datagram for dns header into model
This commit is contained in:
parent
71223309d7
commit
b9ff4c9a51
59
src/main.rs
59
src/main.rs
@ -1,11 +1,9 @@
|
|||||||
use flume::{Receiver, Sender};
|
use flume::{Receiver, Sender};
|
||||||
use std::net::UdpSocket;
|
use std::net::UdpSocket;
|
||||||
use std::thread::{self, JoinHandle};
|
use std::thread::{self, JoinHandle};
|
||||||
use std::convert::TryInto;
|
|
||||||
|
|
||||||
mod proto;
|
mod proto;
|
||||||
use proto::{DNSHeader, DNSOpCode, DNSRCode};
|
use proto::DNSHeader;
|
||||||
|
|
||||||
|
|
||||||
fn listen() -> (JoinHandle<()>, Sender<Vec<u8>>, Receiver<Vec<u8>>) {
|
fn listen() -> (JoinHandle<()>, Sender<Vec<u8>>, Receiver<Vec<u8>>) {
|
||||||
let (tx, rx) = flume::unbounded();
|
let (tx, rx) = flume::unbounded();
|
||||||
@ -31,65 +29,12 @@ fn listen() -> (JoinHandle<()>, Sender<Vec<u8>>, Receiver<Vec<u8>>) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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() {
|
fn main() {
|
||||||
let (thread_udp, _thread_udp_tx, thread_udp_rx) = listen();
|
let (thread_udp, _thread_udp_tx, thread_udp_rx) = listen();
|
||||||
|
|
||||||
for msg in thread_udp_rx.iter() {
|
for msg in thread_udp_rx.iter() {
|
||||||
println!("{:?}", msg);
|
let hdr_struct = DNSHeader::from_udp_datagram(&msg).unwrap();
|
||||||
|
|
||||||
// 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);
|
dbg!(hdr_struct);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = thread_udp.join();
|
let _ = thread_udp.join();
|
||||||
|
102
src/proto.rs
102
src/proto.rs
@ -1,3 +1,5 @@
|
|||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum DNSOpCode {
|
pub enum DNSOpCode {
|
||||||
QUERY = 0,
|
QUERY = 0,
|
||||||
@ -62,16 +64,26 @@ pub struct DNSHeader {
|
|||||||
/// specifies whether this message is a query (false), or a response (true)
|
/// specifies whether this message is a query (false), or a response (true)
|
||||||
pub qr: bool,
|
pub qr: bool,
|
||||||
pub opcode: DNSOpCode,
|
pub opcode: DNSOpCode,
|
||||||
pub authoritative_answer: bool,
|
/// specifies that the responding name server is an authority for the domain name in question section
|
||||||
pub truncated: bool,
|
pub aa: bool,
|
||||||
pub recursion_desired: bool,
|
/// specifies that this message was truncated due to length greater than that permitted on the transmission channel
|
||||||
pub recursion_available: bool,
|
pub tc: bool,
|
||||||
pub authentic_data: bool,
|
/// it directs the name server to pursue the query recursively
|
||||||
pub checking_disabled: bool,
|
pub rd: bool,
|
||||||
pub response_code: DNSRCode,
|
/// denotes whether recursive query support is available in the name server
|
||||||
|
pub ra: bool,
|
||||||
|
/// TODO: add documuentation about this flag
|
||||||
|
pub ad: bool,
|
||||||
|
/// TODO: add documuentation about this flag
|
||||||
|
pub cd: bool,
|
||||||
|
pub rcode: DNSRCode,
|
||||||
|
/// TODO: add documuentation about this count
|
||||||
pub qd_zo_count: u16,
|
pub qd_zo_count: u16,
|
||||||
|
/// TODO: add documuentation about this count
|
||||||
pub an_pr_count: u16,
|
pub an_pr_count: u16,
|
||||||
|
/// TODO: add documuentation about this count
|
||||||
pub ns_up_count: u16,
|
pub ns_up_count: u16,
|
||||||
|
/// TODO: add documuentation about this count
|
||||||
pub ar_count: u16,
|
pub ar_count: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,3 +94,79 @@ pub struct DNSQuery {
|
|||||||
pub qclass: u16,
|
pub qclass: u16,
|
||||||
pub qtype: u16,
|
pub qtype: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DNSHeader {
|
||||||
|
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;
|
||||||
|
|
||||||
|
pub fn from_udp_datagram(datagram: &[u8]) -> Result<Self, &'static str> {
|
||||||
|
if datagram.len() < 11 {
|
||||||
|
return Err("Not enough data");
|
||||||
|
}
|
||||||
|
|
||||||
|
let id = u16::from_be_bytes((&datagram[..2]).try_into().map_err(|_err| "Invalid id")?);
|
||||||
|
|
||||||
|
let flags = u16::from_be_bytes(
|
||||||
|
(&datagram[2..4])
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_err| "Invalid flags")?,
|
||||||
|
);
|
||||||
|
let qr = (flags & DNSHeader::QR_MASK) != 0;
|
||||||
|
let opcode = DNSOpCode::from((flags & DNSHeader::OPCODE_MASK) >> DNSHeader::OPCODE_OFFSET);
|
||||||
|
let aa = (flags & DNSHeader::AA_MASK) != 0;
|
||||||
|
let tc = (flags & DNSHeader::TC_MASK) != 0;
|
||||||
|
let rd = (flags & DNSHeader::RD_MASK) != 0;
|
||||||
|
let ra = (flags & DNSHeader::RA_MASK) != 0;
|
||||||
|
let ad = (flags & DNSHeader::AD_MASK) != 0;
|
||||||
|
let cd = (flags & DNSHeader::CD_MASK) != 0;
|
||||||
|
let rcode = DNSRCode::from((flags & DNSHeader::RCODE_MASK) >> DNSHeader::RCODE_OFFSET);
|
||||||
|
|
||||||
|
let qd_zo_count = u16::from_be_bytes(
|
||||||
|
(&datagram[4..6])
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_err| "Invalid qd_zo_count")?,
|
||||||
|
);
|
||||||
|
let an_pr_count = u16::from_be_bytes(
|
||||||
|
(&datagram[6..8])
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_err| "Invalid an_pr_count")?,
|
||||||
|
);
|
||||||
|
let ns_up_count = u16::from_be_bytes(
|
||||||
|
(&datagram[8..10])
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_err| "Invalid ns_up_count")?,
|
||||||
|
);
|
||||||
|
let ar_count = u16::from_be_bytes(
|
||||||
|
(&datagram[10..12])
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_err| "Invalid ar_count")?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(DNSHeader {
|
||||||
|
id,
|
||||||
|
qr,
|
||||||
|
opcode,
|
||||||
|
aa,
|
||||||
|
tc,
|
||||||
|
rd,
|
||||||
|
ra,
|
||||||
|
ad,
|
||||||
|
cd,
|
||||||
|
rcode,
|
||||||
|
qd_zo_count,
|
||||||
|
an_pr_count,
|
||||||
|
ns_up_count,
|
||||||
|
ar_count,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user