feat: added linting
This commit is contained in:
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"rust-analyzer.check.command": "clippy"
|
||||||
|
}
|
||||||
+2
-1
@@ -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
@@ -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)
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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,
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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}");
|
||||||
|
|||||||
Reference in New Issue
Block a user