1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#![allow(clippy::upper_case_acronyms)]
use nom::bytes::streaming::take;
use nom::number::streaming::be_u16;
use num_enum::TryFromPrimitive;
use sawp_flags::{Flag, Flags};
use std::convert::TryFrom;
use crate::{custom_many0, ErrorFlags, IResult};
#[cfg(feature = "ffi")]
use sawp_ffi::GenerateFFI;
#[derive(Clone, Copy, Debug, PartialEq, TryFromPrimitive)]
#[repr(u16)]
pub enum OptionCode {
LLQ = 1,
UL = 2,
NSID = 3,
DAU = 5,
DHU = 6,
N3U = 7,
EDNSCLIENTSUBNET = 8,
EDNSEXPIRE = 9,
COOKIE = 10,
EDNSTCPKEEPALIVE = 11,
PADDING = 12,
CHAIN = 13,
EDNSKEYTAG = 14,
EDNSERROR = 15,
EDNSCLIENTTAG = 16,
EDNSSERVERTAG = 17,
DEVICEID = 26946,
UNKNOWN,
}
impl OptionCode {
pub fn from_raw(val: u16) -> Self {
OptionCode::try_from(val).unwrap_or(OptionCode::UNKNOWN)
}
}
#[cfg_attr(feature = "ffi", derive(GenerateFFI))]
#[cfg_attr(feature = "ffi", sawp_ffi(prefix = "sawp_dns"))]
#[derive(Debug, PartialEq)]
pub struct EdnsOption {
#[cfg_attr(feature = "ffi", sawp_ffi(copy))]
pub code: OptionCode,
pub data: Vec<u8>,
}
impl EdnsOption {
pub fn parse(input: &[u8]) -> IResult<(EdnsOption, Flags<ErrorFlags>)> {
let (input, (code, inner_error_flags)) = EdnsOption::parse_option_code(input)?;
let (input, option_length) = be_u16(input)?;
let (input, data) = take(option_length)(input)?;
Ok((
input,
(
EdnsOption {
code,
data: data.to_vec(),
},
inner_error_flags,
),
))
}
fn parse_option_code(input: &[u8]) -> IResult<(OptionCode, Flags<ErrorFlags>)> {
let mut error_flags = ErrorFlags::none();
let (input, raw_option_code) = be_u16(input)?;
let code = OptionCode::from_raw(raw_option_code);
if code == OptionCode::UNKNOWN {
error_flags |= ErrorFlags::EdnsParseFail;
}
Ok((input, (code, error_flags)))
}
pub fn parse_options(
input: &[u8],
data_len: u16,
) -> IResult<(Vec<EdnsOption>, Flags<ErrorFlags>)> {
let mut error_flags = ErrorFlags::none();
if data_len < 4 {
return Ok((input, (vec![], error_flags)));
}
let (input, options) = custom_many0(|input| {
let (input, (option, inner_error_flags)) = EdnsOption::parse(input)?;
error_flags |= inner_error_flags;
Ok((input, option))
})(input)?;
Ok((input, (options, error_flags)))
}
}