From 6bc4d823b790a2733b5a5607b240ae636f38a52f Mon Sep 17 00:00:00 2001 From: Arkitu <85173315+Arkitu@users.noreply.github.com> Date: Mon, 28 Apr 2025 21:10:35 +0200 Subject: [PATCH] dns works --- Cargo.lock | 7 +++++ Cargo.toml | 6 ++-- src/dhcp.rs | 6 ++-- src/dns.rs | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 6 ++++ 5 files changed, 108 insertions(+), 5 deletions(-) create mode 100644 src/dns.rs diff --git a/Cargo.lock b/Cargo.lock index a46aa2b..8471634 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -348,6 +348,12 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dnsparse" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18b5892f4beae62ac9681eb96df926ebcebca009e6f2e23a216acf7d3f5c5a97" + [[package]] name = "document-features" version = "0.2.11" @@ -1093,6 +1099,7 @@ dependencies = [ "defmt", "defmt-rtt", "dhcparse", + "dnsparse", "embassy-executor", "embassy-net", "embassy-rp", diff --git a/Cargo.toml b/Cargo.toml index 0cc7a77..e190936 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,8 @@ wifi-connect = [ "dep:serde", ] # you need to add a wifi.conf file for this to work dhcp = ["dep:dhcparse"] -default = ["dhcp"] +dns = ["dep:dnsparse"] +default = ["dhcp", "dns"] [dependencies] embassy-executor = { git = "https://github.com/embassy-rs/embassy", features = [ @@ -54,4 +55,5 @@ serde-json-core = { version = "*", optional = true } serde = { version = "*", optional = true, default-features = false, features = [ "derive", ] } -dhcparse = { version = "*", default-features = false, optional = true } \ No newline at end of file +dhcparse = { version = "*", default-features = false, optional = true } +dnsparse = { version = "*", optional = true } \ No newline at end of file diff --git a/src/dhcp.rs b/src/dhcp.rs index 0103a81..6c65554 100644 --- a/src/dhcp.rs +++ b/src/dhcp.rs @@ -149,9 +149,9 @@ async fn write_dhcp_opts(buf: &mut Vec, op_codes: &[u8]) 1 => (4, &[255, 255, 255, 0]), // DhcpOption::SubnetMask(&dhcpv4::Addr([255, 255, 255, 0])), 2 => (4, &3600_i32.to_be_bytes()), // DhcpOption::TimeOffset(3600), 3 => (4, &[192, 254, 0, 2]), // DhcpOption::Router(&[dhcpv4::Addr([192, 254, 0, 2])]), - 6 => (4, &[0, 0, 0, 0]), // DhcpOption::DomainNameServer(&[dhcpv4::Addr([0, 0, 0, 0])]), - 12 => (4, b"blue"), // DhcpOption::HostName(b"blue"), - 15 => (11, b"LocalDomain"), // DhcpOption::DomainName(b"LocalDomain"), + 6 => (4, &[192, 254, 0, 2]), // DhcpOption::DomainNameServer(&[dhcpv4::Addr([0, 0, 0, 0])]), + 12 => (4, b"blue"), // DhcpOption::HostName(b"blue"), + 15 => (4, b"wifi"), // DhcpOption::DomainName(b"LocalDomain"), 26 => (2, &1514_u16.to_be_bytes()), // DhcpOption::Unknown(26, &[0x5, 0xEA]), // mtu 28 => (4, &[192, 254, 0, 255]), // DhcpOption::Unknown(28, &[192, 254, 0, 255]), // broadcast 51 => (4, &700_u32.to_be_bytes()), // DhcpOption::AddressLeaseTime(700), diff --git a/src/dns.rs b/src/dns.rs new file mode 100644 index 0000000..2280815 --- /dev/null +++ b/src/dns.rs @@ -0,0 +1,88 @@ +use dnsparse::{Answer, Header, HeaderKind, Message, OpCode, QueryClass, QueryKind, ResponseCode}; +use embassy_net::{ + Stack, + udp::{PacketMetadata, UdpSocket}, +}; +use embassy_time::Timer; +use log::{info, warn}; +use pico_website::unwrap; + +#[embassy_executor::task(pool_size = 1)] +pub async fn dns_server(stack: Stack<'static>) { + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + let mut rx_meta = [PacketMetadata::EMPTY; 16]; + let mut tx_meta = [PacketMetadata::EMPTY; 16]; + let mut buf = [0; 4096]; + let mut res_buf = [0; 2048]; + loop { + let mut socket = UdpSocket::new( + stack, + &mut rx_meta, + &mut rx_buffer, + &mut tx_meta, + &mut tx_buffer, + ); + unwrap(socket.bind(53)).await; + + info!("Starting DNS server"); + loop { + let (n, meta) = unwrap(socket.recv_from(&mut buf).await).await; + + let msg = match dnsparse::Message::parse(&mut buf[..n]) { + Ok(msg) => msg, + Err(e) => { + warn!("Dns: Error while parsing DNS message : {:#?}", e); + continue; + } + }; + + if msg.header().opcode() != OpCode::Query { + info!( + "Dns: Received unknown dns opcode ({:?}), ignoring", + msg.header().opcode() + ); + Timer::after_micros(10).await; + continue; + } + let mut res = Message::builder(&mut res_buf) + .header( + Header::builder() + .id(msg.header().id()) + .kind(HeaderKind::Response) + .recursion_available(false) + .recursion_desired(msg.header().recursion_desired()) + .response_code(ResponseCode::NoError) + .build(), + ) + .build(); + for q in msg.questions() { + match q.kind() { + QueryKind::A => { + if q.name() == "ttt.wifi" || q.name() == "www.ttt.wifi" { + res.add_question(&q); + res.add_answer(&Answer { + name: q.name().clone(), + kind: QueryKind::A, + class: QueryClass::IN, + ttl: 60, + rdata: &[192, 254, 0, 2], + }); + info!("Dns: Giving {}", q.name()); + } else { + info!("Dns: Unknown uri, ignoring ({})", q.name()); + } + } + _ => { + continue; + } + }; + } + + if let Err(e) = socket.send_to(res.as_bytes(), meta).await { + warn!("Dns: Error while sending dns response : {:?}", e); + break; + } + } + } +} diff --git a/src/main.rs b/src/main.rs index 03280c3..b0adb48 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,6 +22,9 @@ use {defmt_rtt as _, panic_probe as _}; #[cfg(feature = "dhcp")] mod dhcp; +#[cfg(feature = "dns")] +mod dns; + mod game; mod socket; @@ -163,6 +166,9 @@ async fn main(spawner: Spawner) { #[cfg(feature = "dhcp")] unwrap(spawner.spawn(dhcp::dhcp_server(stack))).await; + #[cfg(feature = "dns")] + unwrap(spawner.spawn(dns::dns_server(stack))).await; + unwrap(spawner.spawn(socket::listen_task(stack, game::Team::Zero, 80))).await; unwrap(spawner.spawn(socket::listen_task(stack, game::Team::One, 81))).await; }