From 08b5947fbb8c795876c8e1945d5bde1bffec225e Mon Sep 17 00:00:00 2001 From: Xander Bil Date: Thu, 29 Feb 2024 23:03:33 +0100 Subject: [PATCH] Byte parser for RR --- src/main.rs | 4 +- src/parser.rs | 127 ++++++++++++++++++++++++++++++++----------------- src/structs.rs | 4 +- 3 files changed, 88 insertions(+), 47 deletions(-) diff --git a/src/main.rs b/src/main.rs index b6a0211..915f3e2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,7 +22,7 @@ async fn create_query(message: Message) -> Message { class: Class::IN, ttl: 4096, rdlength: ip.len() as u16, - rdata: ip, + rdata: vec![1,2,3,4], }; response.header.flags |= 0b1000010110000000; @@ -46,7 +46,7 @@ async fn main() -> Result<(), Box> { tokio::spawn(async move { let response = create_query(message).await; println!("{:?}",response); - let vec = Message::to_bytes(&response); + let vec = Message::to_bytes(response); let decoded = Message::from_bytes(vec.as_slice()); println!("{:?}",decoded); let _ = socket.send_to(vec.as_slice(),addr).await; diff --git a/src/parser.rs b/src/parser.rs index 1f94e0b..8fb6316 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -2,7 +2,7 @@ use std::{mem::size_of, vec}; use crate::{ errors::ParseError, - structs::{Class, Header, Message, Question, Type, RR}, + structs::{Class, Header, LabelString, Message, Question, Type, RR}, }; type Result = std::result::Result; @@ -33,7 +33,7 @@ pub trait FromBytes { fn from_bytes(bytes: &[u8]) -> Result where Self: Sized; - fn to_bytes(s: &Self) -> Vec + fn to_bytes(s: Self) -> Vec where Self: Sized; } @@ -57,7 +57,7 @@ impl FromBytes for Header { } } - fn to_bytes(header: &Self) -> Vec { + fn to_bytes(header: Self) -> Vec { let mut result: [u8; size_of::
()] = [0; size_of::
()]; result[0..2].copy_from_slice(&u16::to_be_bytes(header.id)); @@ -71,6 +71,33 @@ impl FromBytes for Header { } } +impl FromBytes for LabelString { + fn from_bytes(bytes: &[u8]) -> Result { + let mut i = 0; + let mut qname = vec![]; + + // Parse qname labels + while bytes[i] != 0 && bytes[i] as usize + i < bytes.len() { + qname + .push(String::from_utf8(bytes[i + 1..bytes[i] as usize + 1 + i].to_vec()).unwrap()); + i += bytes[i] as usize + 1; + } + + i += 1; + Ok((qname, i)) + } + + fn to_bytes((name, _): Self) -> Vec { + let mut result: Vec = vec![]; + for label in name { + result.push(label.len() as u8); + result.extend(label.as_bytes()); + } + result.push(0); + result + } +} + impl FromBytes for Question { fn from_bytes(bytes: &[u8]) -> Result { // 16 for length octet + zero length octet @@ -80,17 +107,7 @@ impl FromBytes for Question { message: String::from("len of bytes smaller then minimum size"), }) } else { - let mut qname = vec![]; - let mut i = 0; - - // Parse qname labels - while bytes[i] != 0 && bytes[i] as usize + i < bytes.len() { - qname.push( - String::from_utf8(bytes[i + 1..bytes[i] as usize + 1 + i].to_vec()).unwrap(), - ); - i += bytes[i] as usize + 1; - } - i += 1; + let (qname, i) = LabelString::from_bytes(bytes)?; if bytes.len() - i < size_of::() + size_of::() { Err(ParseError { @@ -122,13 +139,8 @@ impl FromBytes for Question { } } - fn to_bytes(question: &Self) -> Vec { - let mut result: Vec = vec![]; - for label in &question.qname { - result.push(label.len() as u8); - result.extend(label.as_bytes()); - } - result.push(0); + fn to_bytes(question: Self) -> Vec { + let mut result = LabelString::to_bytes((question.qname, 0)); result.extend(u16::to_be_bytes(question.qtype.to_owned() as u16)); result.extend(u16::to_be_bytes(question.qclass.to_owned() as u16)); result @@ -136,28 +148,55 @@ impl FromBytes for Question { } impl FromBytes for RR { - fn from_bytes(bytes: &[u8]) -> Result - where - Self: Sized, - { - todo!() + fn from_bytes(bytes: &[u8]) -> Result { + let (name, i) = LabelString::from_bytes(bytes)?; + if bytes.len() - i < size_of::() + size_of::() + 6 { + Err(ParseError { + object: String::from("RR"), + message: String::from("len of rest of bytes smaller then minimum size"), + }) + } else { + let _type = Type::try_from(u16::from_be_bytes(bytes[i..i + 2].try_into().unwrap())) + .map_err(|_| ParseError { + object: String::from("Type"), + message: String::from("invalid"), + })?; + + let class = + Class::try_from(u16::from_be_bytes(bytes[i + 2..i + 4].try_into().unwrap())) + .map_err(|_| ParseError { + object: String::from("Class"), + message: String::from("invalid"), + })?; + + let ttl = i32::from_be_bytes(bytes[i + 4..i + 8].try_into().unwrap()); + let rdlength = u16::from_be_bytes(bytes[i + 8..i + 10].try_into().unwrap()); + + if bytes.len() - i - 10 != rdlength as usize { + Err(ParseError { + object: String::from("RR"), + message: String::from("len of rest of bytes not equal to rdlength"), + }) + } else { + Ok(RR { + name, + _type, + class, + ttl, + rdlength, + rdata: bytes[i + 10..].to_vec(), + }) + } + } } - fn to_bytes(rr: &Self) -> Vec { - let mut result = vec![]; - for label in &rr.name { - result.push(label.len() as u8); - result.extend(label.as_bytes()); - } - result.push(0); + fn to_bytes(rr: Self) -> Vec { + let mut result = LabelString::to_bytes((rr.name, 0)); result.extend(u16::to_be_bytes(rr._type.to_owned() as u16)); result.extend(u16::to_be_bytes(rr.class.to_owned() as u16)); result.extend(i32::to_be_bytes(rr.ttl.to_owned())); result.extend(u16::to_be_bytes(4 as u16)); - result.push(93); - result.push(184); - result.push(216); - result.push(34); + result.extend(rr.rdata); result } } @@ -175,19 +214,19 @@ impl FromBytes for Message { }) } - fn to_bytes(message: &Self) -> Vec { + fn to_bytes(message: Self) -> Vec { let mut result = vec![]; - result.extend(Header::to_bytes(&message.header)); - result.extend(Question::to_bytes(&message.question)); + result.extend(Header::to_bytes(message.header)); + result.extend(Question::to_bytes(message.question)); if message.answer.is_some() { - result.extend(RR::to_bytes(&message.answer.clone().unwrap())); + result.extend(RR::to_bytes(message.answer.unwrap())); } if message.authority.is_some() { - result.extend(RR::to_bytes(&message.authority.clone().unwrap())); + result.extend(RR::to_bytes(message.authority.unwrap())); } if message.additional.is_some() { - result.extend(RR::to_bytes(&message.additional.clone().unwrap())); - } + result.extend(RR::to_bytes(message.additional.unwrap())); + } result } } diff --git a/src/structs.rs b/src/structs.rs index 489c373..7eeaacd 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -43,9 +43,11 @@ pub struct RR { pub class: Class, pub ttl: i32, pub rdlength: u16, - pub rdata: String, + pub rdata: Vec, } +pub type LabelString = (Vec,usize); + #[derive(Debug)] pub struct Response { field: Type,