From df255f926715adb56439e60b116ee4e64cecae25 Mon Sep 17 00:00:00 2001 From: ddidderr Date: Sun, 8 May 2022 16:48:15 +0200 Subject: [PATCH] (tests) rcode parsing tests (#22) Check if valid and invalid response codes are parsed correctly. Reviewed-on: https://git.comff.net/rustics/dns/pulls/22 Co-authored-by: ddidderr Co-committed-by: ddidderr --- src/proto.rs | 84 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 70 insertions(+), 14 deletions(-) diff --git a/src/proto.rs b/src/proto.rs index 7680a7e..c26d676 100644 --- a/src/proto.rs +++ b/src/proto.rs @@ -74,7 +74,7 @@ impl TryFrom for DNSOpCode { /// /// 65,535 /// 0xFFFF Reserved; can only be allocated by Standards Action. -#[derive(Debug)] +#[derive(Debug, PartialEq, Copy, Clone)] pub enum DNSRCode { NoError = 0, FormErr = 1, @@ -110,7 +110,7 @@ impl TryFrom for DNSRCode { } } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone, Copy)] pub enum DNSMessageType { Query, Response, @@ -125,7 +125,7 @@ impl From for DNSMessageType { } } -#[derive(Debug)] +#[derive(Debug, Clone, PartialEq)] pub struct DNSHeader { /// used by the requester to match up replies to outstanding queries pub id: u16, @@ -155,7 +155,7 @@ pub struct DNSHeader { pub additional_count: u16, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct DNSQuery { pub hdr: DNSHeader, pub name: String, @@ -219,7 +219,7 @@ impl DNSHeader { } } -#[derive(Debug, PartialEq)] +#[derive(Debug, Clone, PartialEq)] pub enum DNSParseError { DatagramTooShort, DNSOpCodeInvalid, @@ -228,7 +228,9 @@ pub enum DNSParseError { #[cfg(test)] mod tests { + use super::*; + #[test] fn parse_dns_header_too_short() { // minimal header with 1 byte missing @@ -264,20 +266,19 @@ mod tests { let mut dns_query = [ 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; - let valid_opcodes = [0, 1, 2, 4, 5]; - let valid_parsed_opcodes = [ - DNSOpCode::Query, - DNSOpCode::IQuery, - DNSOpCode::Status, - DNSOpCode::Notify, - DNSOpCode::Update, + let valid_opcodes = [ + (0, DNSOpCode::Query), + (1, DNSOpCode::IQuery), + (2, DNSOpCode::Status), + (4, DNSOpCode::Notify), + (5, DNSOpCode::Update), ]; - for (idx, opcode) in valid_opcodes.iter().enumerate() { + for (opcode, parsed_opcode) in valid_opcodes { dns_query[2] = opcode << 3; let parse_result = DNSHeader::from_udp_datagram(&dns_query); assert_eq!( - parse_result?.opcode, valid_parsed_opcodes[idx], + parse_result?.opcode, parsed_opcode, "query: {:02x?}, opcode: {}", dns_query, opcode ); @@ -304,4 +305,59 @@ mod tests { assert_eq!(parse_result?.message_type, DNSMessageType::Response); Ok(()) } + + #[test] + fn parse_dns_header_response_code_invalid() { + let mut dns_query = [ + 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + let invalid_rcodes = [11, 12, 13, 14, 15]; + + for rcode in invalid_rcodes { + dns_query[3] = (rcode as u8) << 0; + + let parse_result = DNSHeader::from_udp_datagram(&dns_query); + + assert_eq!( + parse_result, + Err(DNSParseError::DNSRCodeInvalid), + "query: {:02x?}, rcode: {}", + dns_query, + rcode, + ); + } + } + + #[test] + fn parse_dns_header_response_code_valid() -> Result<(), DNSParseError> { + let mut dns_query = [ + 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + + // for now we only support RCodes 0 to 10 (inclusive) + let valid_rcodes = [ + (0, DNSRCode::NoError), + (1, DNSRCode::FormErr), + (2, DNSRCode::ServFail), + (3, DNSRCode::NXDomain), + (4, DNSRCode::NotImp), + (5, DNSRCode::Refused), + (6, DNSRCode::YXDomain), + (7, DNSRCode::YXRRSet), + (8, DNSRCode::NXRRSet), + (9, DNSRCode::NotAuth), + (10, DNSRCode::NotZone), + ]; + + for (rcode, parsed_rcode) in valid_rcodes { + dns_query[3] = rcode << 0; + let parse_result = DNSHeader::from_udp_datagram(&dns_query); + assert_eq!( + parse_result?.response_code, parsed_rcode, + "query: {:02x?}, rcode: {}, parsed_rcode: {:?}", + dns_query, rcode, parsed_rcode + ); + } + Ok(()) + } }