commit 71223309d79a289164936f7c6b26b2ec31bc359e Author: Tobias Ottenweller Date: Sun Mar 13 21:56:17 2022 +0100 Code for parsing headers added. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..18a582d --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,238 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bumpalo" +version = "3.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "dns-parse" +version = "0.1.0" +dependencies = [ + "flume", +] + +[[package]] +name = "flume" +version = "0.10.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843c03199d0c0ca54bc1ea90ac0d507274c28abcc4f691ae8b4eaa375087c76a" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "pin-project", + "spin", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-sink" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" + +[[package]] +name = "getrandom" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "js-sys" +version = "0.3.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" + +[[package]] +name = "lock_api" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom", +] + +[[package]] +name = "pin-project" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "spin" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5" +dependencies = [ + "lock_api", +] + +[[package]] +name = "syn" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "wasm-bindgen" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..cd286f5 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "dns-parse" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +flume = "0.10" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..1917d5d --- /dev/null +++ b/src/main.rs @@ -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>, Receiver>) { + 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(); +} diff --git a/src/proto.rs b/src/proto.rs new file mode 100644 index 0000000..177e557 --- /dev/null +++ b/src/proto.rs @@ -0,0 +1,84 @@ +#[derive(Debug)] +pub enum DNSOpCode { + QUERY = 0, + IQUERY = 1, // obsolete + STATUS = 2, + NOTIFY = 4, + UPDATE = 5, +} + +impl From 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 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, +} diff --git a/udp_sender.py b/udp_sender.py new file mode 100755 index 0000000..e5f68a5 --- /dev/null +++ b/udp_sender.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 +import socket +import sys + + +UDP_SIZE = int(sys.argv[1]) + +UDP_IP = "127.0.0.1" +UDP_PORT = 13337 +MESSAGE = "A" + +sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +sock.sendto(bytes(MESSAGE*UDP_SIZE, "utf-8"), (UDP_IP, UDP_PORT)) \ No newline at end of file