feat: added linting

This commit is contained in:
2026-07-07 18:27:45 +02:00
parent 9c0f296aa8
commit d2f03dcd2f
9 changed files with 44 additions and 29 deletions
+3
View File
@@ -0,0 +1,3 @@
{
"rust-analyzer.check.command": "clippy"
}
+2 -1
View File
@@ -2,6 +2,7 @@ use anyhow::{Result, ensure};
use serde::Deserialize; use serde::Deserialize;
#[derive(Deserialize)] #[derive(Deserialize)]
#[allow(clippy::upper_case_acronyms)]
pub enum EntryType { pub enum EntryType {
A, A,
AAAA, AAAA,
@@ -61,7 +62,7 @@ pub fn load() -> Result<ConfigData> {
}; };
for entry in &mut file_config.entries { for entry in &mut file_config.entries {
let address_parts: Vec<&str> = entry.address.split(".").collect(); let address_parts: Vec<&str> = entry.address.split('.').collect();
ensure!(address_parts.len() == 4, "Invalid IP address"); ensure!(address_parts.len() == 4, "Invalid IP address");
entry.address_bytes = [ entry.address_bytes = [
address_parts[0].parse()?, address_parts[0].parse()?,
+3 -3
View File
@@ -17,7 +17,7 @@ pub struct Answer {
} }
impl Answer { impl Answer {
pub fn parse(datagram: &mut Cursor<&[u8]>) -> Result<Answer> { pub fn parse(datagram: &mut Cursor<&[u8]>) -> Result<Self> {
let domain = parse_domain(datagram)?; let domain = parse_domain(datagram)?;
let record_type = datagram.read_u16()?; let record_type = datagram.read_u16()?;
@@ -27,7 +27,7 @@ impl Answer {
let data = datagram.read_bytes(data_length)?; let data = datagram.read_bytes(data_length)?;
Ok(Answer { Ok(Self {
domain, domain,
record_type, record_type,
class, class,
@@ -42,7 +42,7 @@ impl Answer {
result.extend(self.record_type.to_be_bytes()); result.extend(self.record_type.to_be_bytes());
result.extend(self.class.to_be_bytes()); result.extend(self.class.to_be_bytes());
result.extend(self.ttl.to_be_bytes()); result.extend(self.ttl.to_be_bytes());
result.extend((self.data.len() as u16).to_be_bytes()); result.extend(u16::try_from(self.data.len())?.to_be_bytes());
result.extend_from_slice(&self.data); result.extend_from_slice(&self.data);
Ok(result) Ok(result)
+2 -2
View File
@@ -57,7 +57,7 @@ pub fn domain_to_bytes(domain: &str) -> Result<Vec<u8>> {
return Ok(result); return Ok(result);
} }
for part in domain.split(".") { for part in domain.split('.') {
if part.len() > 63 { if part.len() > 63 {
bail!("domain label too long"); bail!("domain label too long");
} }
@@ -65,7 +65,7 @@ pub fn domain_to_bytes(domain: &str) -> Result<Vec<u8>> {
bail!("empty domain label"); bail!("empty domain label");
} }
result.push(part.len() as u8); result.push(u8::try_from(part.len())?);
result.extend_from_slice(part.as_bytes()); result.extend_from_slice(part.as_bytes());
} }
result.push(0); result.push(0);
+5 -4
View File
@@ -5,6 +5,7 @@ use anyhow::Result;
use crate::ext::CursorExt; use crate::ext::CursorExt;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[allow(clippy::struct_excessive_bools)]
pub struct Header { pub struct Header {
pub transaction_id: u16, pub transaction_id: u16,
pub query_response: bool, pub query_response: bool,
@@ -23,7 +24,7 @@ pub struct Header {
} }
impl Header { impl Header {
pub fn parse(cursor: &mut Cursor<&[u8]>) -> Result<Header> { pub fn parse(cursor: &mut Cursor<&[u8]>) -> Result<Self> {
let transaction_id = cursor.read_u16()?; let transaction_id = cursor.read_u16()?;
let flags1 = cursor.read_u8()?; let flags1 = cursor.read_u8()?;
let flags2 = cursor.read_u8()?; let flags2 = cursor.read_u8()?;
@@ -32,7 +33,7 @@ impl Header {
let number_of_authority_resource_records = cursor.read_u16()?; let number_of_authority_resource_records = cursor.read_u16()?;
let number_of_additional_resource_records = cursor.read_u16()?; let number_of_additional_resource_records = cursor.read_u16()?;
let datagram = Header { let datagram = Self {
transaction_id, transaction_id,
query_response: flags1 & (1 << 7) > 0, query_response: flags1 & (1 << 7) > 0,
op_code: (flags1 >> 3) & 0x0F, op_code: (flags1 >> 3) & 0x0F,
@@ -52,7 +53,7 @@ impl Header {
Ok(datagram) Ok(datagram)
} }
pub fn to_bytes(&self) -> Result<Vec<u8>> { pub fn to_bytes(&self) -> Vec<u8> {
let mut buffer = [0u8; 12]; let mut buffer = [0u8; 12];
let transaction_id = self.transaction_id.to_be_bytes(); let transaction_id = self.transaction_id.to_be_bytes();
let number_of_questions = self.number_of_questions.to_be_bytes(); let number_of_questions = self.number_of_questions.to_be_bytes();
@@ -96,6 +97,6 @@ impl Header {
buffer[10] = number_of_additional_resource_records[0]; buffer[10] = number_of_additional_resource_records[0];
buffer[11] = number_of_additional_resource_records[1]; buffer[11] = number_of_additional_resource_records[1];
Ok(buffer.into()) buffer.into()
} }
} }
+6 -6
View File
@@ -12,11 +12,11 @@ pub struct Message {
} }
impl Message { impl Message {
pub fn parse(datagram: &mut Cursor<&[u8]>) -> Result<Message> { pub fn parse(datagram: &mut Cursor<&[u8]>) -> Result<Self> {
let header = Header::parse(datagram)?; let header = Header::parse(datagram)?;
let mut message = Message { let mut message = Self {
header: header, header,
questions: vec![], questions: vec![],
answers: vec![], answers: vec![],
}; };
@@ -35,7 +35,7 @@ impl Message {
pub fn to_bytes(&self) -> Result<Vec<u8>> { pub fn to_bytes(&self) -> Result<Vec<u8>> {
let mut result: Vec<u8> = vec![]; let mut result: Vec<u8> = vec![];
result.extend(self.header.to_bytes()?); result.extend(self.header.to_bytes());
for question in &self.questions { for question in &self.questions {
result.extend(question.to_bytes()?); result.extend(question.to_bytes()?);
} }
@@ -45,8 +45,8 @@ impl Message {
Ok(result) Ok(result)
} }
pub fn prepare_response(&self) -> Message { pub fn prepare_response(&self) -> Self {
Message { Self {
header: Header { header: Header {
transaction_id: self.header.transaction_id, transaction_id: self.header.transaction_id,
query_response: true, query_response: true,
+1
View File
@@ -14,6 +14,7 @@ pub use question::*;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#![allow(clippy::unwrap_used)]
use std::io::Cursor; use std::io::Cursor;
use super::*; use super::*;
+8 -8
View File
@@ -10,21 +10,21 @@ use crate::{
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Question { pub struct Question {
pub domain: String, pub domain: String,
pub question_type: u16, pub qtype: u16,
pub question_class: u16, pub class: u16,
} }
impl Question { impl Question {
pub fn parse(cursor: &mut Cursor<&[u8]>) -> Result<Question> { pub fn parse(cursor: &mut Cursor<&[u8]>) -> Result<Self> {
let domain = parse_domain(cursor)?; let domain = parse_domain(cursor)?;
let question_type = cursor.read_u16()?; let question_type = cursor.read_u16()?;
let question_class = cursor.read_u16()?; let question_class = cursor.read_u16()?;
let question = Question { let question = Self {
domain, domain,
question_type, qtype: question_type,
question_class, class: question_class,
}; };
Ok(question) Ok(question)
@@ -32,8 +32,8 @@ impl Question {
pub fn to_bytes(&self) -> Result<Vec<u8>> { pub fn to_bytes(&self) -> Result<Vec<u8>> {
let mut result = domain_to_bytes(&self.domain)?; let mut result = domain_to_bytes(&self.domain)?;
result.extend(self.question_type.to_be_bytes()); result.extend(self.qtype.to_be_bytes());
result.extend(self.question_class.to_be_bytes()); result.extend(self.class.to_be_bytes());
Ok(result) Ok(result)
} }
} }
+14 -5
View File
@@ -1,3 +1,9 @@
#![warn(clippy::pedantic)]
#![warn(clippy::nursery)]
#![warn(clippy::unwrap_used)]
#![warn(clippy::todo)]
#![warn(clippy::panic)]
mod config; mod config;
mod dns; mod dns;
mod ext; mod ext;
@@ -11,7 +17,10 @@ use dotenv::dotenv;
use tokio::net::UdpSocket; use tokio::net::UdpSocket;
use tracing::{Instrument, Level}; use tracing::{Instrument, Level};
use crate::{config::ConfigData, dns::*}; use crate::{
config::ConfigData,
dns::{Answer, CLASS_IN, Message, Question, RECORD_TYPE_A, RESPONSE_CODE_NXDOMAIN},
};
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {
@@ -61,17 +70,17 @@ async fn handle_datagram(
let mut response = message.prepare_response(); let mut response = message.prepare_response();
for question in message.questions { for question in message.questions {
if question.question_class != CLASS_IN { if question.class != CLASS_IN {
tracing::error!( tracing::error!(
"only IN class records are supported yet, requested: {}", "only IN class records are supported yet, requested: {}",
question.question_class question.class
); );
return Ok(()); return Ok(());
} }
match question.question_type { match question.qtype {
RECORD_TYPE_A => { RECORD_TYPE_A => {
handle_type_a_question(&config, &question, &mut response); handle_type_a_question(config, &question, &mut response);
} }
qt => { qt => {
tracing::error!("unsupported question type, requested: {qt}"); tracing::error!("unsupported question type, requested: {qt}");