Skip to content

Commit b96073f

Browse files
authored
Merge pull request #27 from LinkTed/nightly
Version 0.9.0
2 parents cfe9f76 + 5164cbd commit b96073f

31 files changed

+487
-87
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "dns-message-parser"
3-
version = "0.8.0"
3+
version = "0.9.0"
44
authors = ["LinkTed <[email protected]>"]
55
edition = "2018"
66
readme = "README.md"
@@ -28,7 +28,7 @@ hex = "0.4"
2828
thiserror = "2"
2929

3030
[dev-dependencies]
31-
criterion = "0.5"
31+
criterion = "0.6"
3232

3333
[[bench]]
3434
name = "message"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ A library to encode and decode DNS packets ([RFC1035](https://tools.ietf.org/htm
1313
Add this to your `Cargo.toml`:
1414
```toml
1515
[dependencies]
16-
dns-message-parser = "0.7.0"
16+
dns-message-parser = "0.9.0"
1717
```
1818

1919
## Example

src/decode/decoder.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ impl<'a, 'b: 'a> Decoder<'a, 'b> {
2929
}
3030
}
3131

32-
pub(super) fn new_main_offset(&self, offset: usize) -> Decoder<'static, 'static> {
32+
pub(super) fn new_main_offset(&self, offset: u16) -> Decoder<'static, 'static> {
3333
let main = self.get_main();
3434
Decoder {
3535
parent: None,
3636
bytes: main.bytes.clone(),
37-
offset,
37+
offset: offset as usize,
3838
}
3939
}
4040

@@ -57,6 +57,14 @@ impl<'a, 'b: 'a> Decoder<'a, 'b> {
5757
}
5858
}
5959

60+
pub(super) fn remaining(&self) -> DecodeResult<usize> {
61+
let bytes_len = self.bytes.len();
62+
match bytes_len.checked_sub(self.offset) {
63+
Some(remaining) => Ok(remaining),
64+
None => Err(DecodeError::NotEnoughBytes(bytes_len, self.offset)),
65+
}
66+
}
67+
6068
pub(super) fn finished(self) -> DecodeResult<()> {
6169
match self.is_finished()? {
6270
true => Ok(()),

src/decode/domain_name.rs

Lines changed: 48 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{
22
decode::Decoder, domain_name::DOMAIN_NAME_MAX_RECURSION, DecodeError, DecodeResult, DomainName,
33
};
4-
use std::{collections::HashSet, str::from_utf8, usize};
4+
use std::{collections::HashSet, str::from_utf8};
55

66
const COMPRESSION_BITS: u8 = 0b1100_0000;
77
const COMPRESSION_BITS_REV: u8 = 0b0011_1111;
@@ -12,67 +12,75 @@ const fn is_compressed(length: u8) -> bool {
1212
}
1313

1414
#[inline]
15-
const fn get_offset(length_1: u8, length_2: u8) -> usize {
16-
(((length_1 & COMPRESSION_BITS_REV) as usize) << 8) | length_2 as usize
15+
const fn get_offset(length_1: u8, length_2: u8) -> u16 {
16+
(((length_1 & COMPRESSION_BITS_REV) as u16) << 8) | length_2 as u16
17+
}
18+
19+
enum DomainNameLength {
20+
Compressed(u16),
21+
Label(u8),
1722
}
1823

1924
impl<'a, 'b: 'a> Decoder<'a, 'b> {
25+
fn domain_name_length(&mut self) -> DecodeResult<DomainNameLength> {
26+
let length = self.u8()?;
27+
if is_compressed(length) {
28+
let offset = self.u8()?;
29+
Ok(DomainNameLength::Compressed(get_offset(length, offset)))
30+
} else {
31+
Ok(DomainNameLength::Label(length))
32+
}
33+
}
34+
2035
pub(super) fn domain_name(&mut self) -> DecodeResult<DomainName> {
2136
let mut domain_name = DomainName::default();
2237

23-
let mut length = self.u8()?;
24-
while length != 0 {
25-
if is_compressed(length) {
26-
let mut recursions = HashSet::new();
27-
self.domain_name_recursion(&mut domain_name, &mut recursions, length)?;
28-
return Ok(domain_name);
29-
} else {
30-
length = self.domain_name_label(&mut domain_name, length)?;
38+
loop {
39+
match self.domain_name_length()? {
40+
DomainNameLength::Compressed(offset) => {
41+
self.domain_name_recursion(&mut domain_name, offset)?;
42+
return Ok(domain_name);
43+
}
44+
DomainNameLength::Label(0) => return Ok(domain_name),
45+
DomainNameLength::Label(length) => {
46+
self.domain_name_label(&mut domain_name, length)?
47+
}
3148
}
3249
}
33-
Ok(domain_name)
3450
}
3551

36-
fn domain_name_label(&mut self, domain_name: &mut DomainName, length: u8) -> DecodeResult<u8> {
52+
fn domain_name_label(&mut self, domain_name: &mut DomainName, length: u8) -> DecodeResult<()> {
3753
let buffer = self.read(length as usize)?;
3854
let label = from_utf8(buffer.as_ref())?;
3955
let label = label.parse()?;
4056
domain_name.append_label(label)?;
41-
self.u8()
57+
Ok(())
4258
}
4359

44-
fn domain_name_recursion(
45-
&mut self,
46-
domain_name: &mut DomainName,
47-
recursions: &mut HashSet<usize>,
48-
mut length: u8,
49-
) -> DecodeResult<()> {
50-
let mut buffer = self.u8()?;
51-
let mut offset = get_offset(length, buffer);
60+
fn domain_name_recursion(&self, domain_name: &mut DomainName, offset: u16) -> DecodeResult<()> {
5261
let mut decoder = self.new_main_offset(offset);
62+
let mut recursions = HashSet::new();
5363

54-
length = decoder.u8()?;
55-
56-
while length != 0 {
57-
if is_compressed(length) {
58-
buffer = decoder.u8()?;
59-
offset = get_offset(length, buffer);
60-
if recursions.insert(offset) {
61-
let recursions_len = recursions.len();
62-
if recursions_len > DOMAIN_NAME_MAX_RECURSION {
63-
return Err(DecodeError::MaxRecursion(recursions_len));
64+
loop {
65+
match decoder.domain_name_length()? {
66+
DomainNameLength::Compressed(offset) => {
67+
if recursions.insert(offset) {
68+
let recursions_len = recursions.len();
69+
if recursions_len > DOMAIN_NAME_MAX_RECURSION {
70+
return Err(DecodeError::MaxRecursion(recursions_len));
71+
}
72+
} else {
73+
return Err(DecodeError::EndlessRecursion(offset));
6474
}
65-
} else {
66-
return Err(DecodeError::EndlessRecursion(offset));
75+
76+
decoder.offset = offset as usize;
77+
}
78+
DomainNameLength::Label(0) => return Ok(()),
79+
DomainNameLength::Label(length) => {
80+
decoder.domain_name_label(domain_name, length)?;
6781
}
68-
decoder.offset = offset as usize;
69-
length = decoder.u8()?;
70-
} else {
71-
length = decoder.domain_name_label(domain_name, length)?;
7282
}
7383
}
74-
75-
Ok(())
7684
}
7785
}
7886

src/decode/error.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::rr::edns::CookieError;
1+
use crate::rr::edns::{CookieError, ExtendedDNSErrorExtraTextError};
22
use crate::rr::{AddressError, Class, ISDNError, PSDNAddressError, TagError, Type};
33
use crate::{Dns, DomainName, DomainNameError, LabelError};
44
use hex::FromHexError;
@@ -69,6 +69,10 @@ pub enum DecodeError {
6969
CookieError(#[from] CookieError),
7070
#[error("Could not decode AddressNumber: {0}")]
7171
EcsAddressNumber(u16),
72+
#[error("Could not decode EcsAddressNumber: {0}")]
73+
ExtendedDNSErrorCodes(u16),
74+
#[error("Could not decode ExtendedDNSErrorExtraText: {0}")]
75+
ExtendedDNSErrorExtraTextError(#[from] ExtendedDNSErrorExtraTextError),
7276
#[error("The IPv4 Address is too big: {0}")]
7377
EcsTooBigIpv4Address(usize),
7478
#[error("The IPv6 Address is too big: {0}")]
@@ -90,7 +94,7 @@ pub enum DecodeError {
9094
#[error("Could not decode the domain name, the because maximum recursion is reached: {0}")]
9195
MaxRecursion(usize),
9296
#[error("Could not decode the domain name, because an endless recursion was detected: {0}")]
93-
EndlessRecursion(usize),
97+
EndlessRecursion(u16),
9498
#[error("The are remaining bytes, which was not parsed")]
9599
RemainingBytes(usize, Dns),
96100
#[error("Padding is not zero: {0}")]

src/decode/helpers.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,12 @@ impl<'a, 'b: 'a> Decoder<'a, 'b> {
2727
Ok(buffer.get_u64())
2828
}
2929

30-
pub(super) fn string(&mut self) -> DecodeResult<String> {
30+
pub(super) fn string_with_len(&mut self) -> DecodeResult<String> {
3131
let length = self.u8()? as usize;
32+
self.string(length)
33+
}
34+
35+
pub(super) fn string(&mut self, length: usize) -> DecodeResult<String> {
3236
let buffer = self.read(length)?;
3337
let string = from_utf8(buffer.as_ref())?;
3438
Ok(String::from(string))

src/decode/rr/draft_ietf_dnsop_svcb_https.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ impl<'a, 'b: 'a> Decoder<'a, 'b> {
5151
/// Decode a single service parameter
5252
///
5353
/// Parameters:
54-
/// - `service_parameter_key` - the IANA-controlled numeric identifier as defined in section
55-
/// 14.3 of the RFC
54+
/// - `service_parameter_key` - the IANA-controlled numeric identifier as defined in section 14.3 of the RFC
5655
///
5756
/// Returns:
5857
/// - `Ok(ServiceParameter)` - if there were no issues decoding the value
@@ -72,7 +71,7 @@ impl<'a, 'b: 'a> Decoder<'a, 'b> {
7271
1 => {
7372
let mut alpn_ids = vec![];
7473
while !self.is_finished()? {
75-
alpn_ids.push(self.string()?);
74+
alpn_ids.push(self.string_with_len()?);
7675
}
7776
ServiceParameter::ALPN { alpn_ids }
7877
}

src/decode/rr/edns/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ mod rfc_6891;
22
mod rfc_7830;
33
mod rfc_7871;
44
mod rfc_7873;
5+
mod rfc_8914;

src/decode/rr/edns/rfc_6891.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,16 @@ impl<'a, 'b: 'a> Decoder<'b, 'b> {
2525
fn rr_edns_option(&'a mut self) -> DecodeResult<EDNSOption> {
2626
let edns_option_code = self.rr_edns_option_code()?;
2727
let edns_option_length = self.u16()?;
28-
let mut ends_option_data = self.sub(edns_option_length)?;
28+
let mut edns_option_data = self.sub(edns_option_length)?;
2929
let edns_option = match edns_option_code {
30-
EDNSOptionCode::ECS => EDNSOption::ECS(ends_option_data.rr_edns_ecs()?),
31-
EDNSOptionCode::Cookie => EDNSOption::Cookie(ends_option_data.rr_edns_cookie()?),
32-
EDNSOptionCode::Padding => EDNSOption::Padding(ends_option_data.rr_edns_padding()?),
30+
EDNSOptionCode::ECS => EDNSOption::ECS(edns_option_data.rr_edns_ecs()?),
31+
EDNSOptionCode::Cookie => EDNSOption::Cookie(edns_option_data.rr_edns_cookie()?),
32+
EDNSOptionCode::Padding => EDNSOption::Padding(edns_option_data.rr_edns_padding()?),
33+
EDNSOptionCode::ExtendedDnsError => {
34+
EDNSOption::ExtendedDNSErrors(edns_option_data.rr_edns_extended_dns_errors()?)
35+
}
3336
};
34-
ends_option_data.finished()?;
37+
edns_option_data.finished()?;
3538
Ok(edns_option)
3639
}
3740

src/decode/rr/edns/rfc_8914.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
use crate::decode::Decoder;
2+
use crate::rr::edns::{ExtendedDNSErrorCodes, ExtendedDNSErrorExtraText, ExtendedDNSErrors};
3+
use crate::{DecodeError, DecodeResult};
4+
use std::convert::TryFrom;
5+
6+
impl<'a, 'b: 'a> Decoder<'a, 'b> {
7+
fn rr_edns_extended_dns_error_codes(&mut self) -> DecodeResult<ExtendedDNSErrorCodes> {
8+
let buffer = self.u16()?;
9+
match ExtendedDNSErrorCodes::try_from(buffer) {
10+
Ok(edns_extended_dns_errors_codes) => Ok(edns_extended_dns_errors_codes),
11+
Err(buffer) => Err(DecodeError::ExtendedDNSErrorCodes(buffer)),
12+
}
13+
}
14+
15+
fn rr_edns_extended_dns_errors_extra_text(
16+
&mut self,
17+
) -> DecodeResult<ExtendedDNSErrorExtraText> {
18+
let extended_dns_errors_extra_text =
19+
ExtendedDNSErrorExtraText::try_from(self.string(self.remaining()?)?)?;
20+
Ok(extended_dns_errors_extra_text)
21+
}
22+
23+
pub(super) fn rr_edns_extended_dns_errors(&mut self) -> DecodeResult<ExtendedDNSErrors> {
24+
println!("AA");
25+
let info_code = self.rr_edns_extended_dns_error_codes()?;
26+
println!("AA");
27+
let extra_text = self.rr_edns_extended_dns_errors_extra_text()?;
28+
println!("AA {0}", extra_text.as_ref().is_empty());
29+
Ok(ExtendedDNSErrors {
30+
info_code,
31+
extra_text,
32+
})
33+
}
34+
}

0 commit comments

Comments
 (0)