Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Open sidebar
DNS Witch
Nomilo
Commits
7155c1cc
Commit
7155c1cc
authored
Mar 20, 2021
by
Gaël Berthaud-Müller
Browse files
improve rdata deserialization support and better implemetation of get zones records
parent
1a238ea0
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
144 additions
and
46 deletions
+144
-46
Cargo.lock
Cargo.lock
+1
-0
Cargo.toml
Cargo.toml
+1
-0
src/main.rs
src/main.rs
+10
-4
src/types/dns.rs
src/types/dns.rs
+122
-42
src/types/mod.rs
src/types/mod.rs
+10
-0
No files found.
Cargo.lock
View file @
7155c1cc
...
...
@@ -710,6 +710,7 @@ dependencies = [
name = "nomilo"
version = "0.1.0-dev"
dependencies = [
"base64 0.13.0",
"rocket",
"rocket_contrib",
"serde",
...
...
Cargo.toml
View file @
7155c1cc
...
...
@@ -14,3 +14,4 @@ serde_json = "1.0"
rocket
=
"0.4.7"
rocket_contrib
=
{
version
=
"0.4"
,
default-features
=
false
,
features
=
["json"]
}
toml
=
"0.5"
base64
=
"0.13.0"
src/main.rs
View file @
7155c1cc
...
...
@@ -19,11 +19,17 @@ fn zone_records(client: State<SyncClient<TcpClientConnection>>, zone: String) ->
// TODO: Implement FromParam for Name
let
name
=
Name
::
from_str
(
&
zone
)
.unwrap
();
// TODO: add support for all trust-dns record types
// then use AXFR here and filter out dnssec related fields
let
response
:
DnsResponse
=
client
.query
(
&
name
,
DNSClass
::
IN
,
RecordType
::
AAAA
)
.unwrap
();
let
response
:
DnsResponse
=
client
.query
(
&
name
,
DNSClass
::
IN
,
RecordType
::
AXFR
)
.unwrap
();
let
answers
:
&
[
Record
]
=
response
.answers
();
let
records
:
Vec
<
types
::
dns
::
Record
>
=
answers
.to_vec
()
.into_iter
()
.map
(|
record
|
record
.into
())
.collect
();
let
mut
records
:
Vec
<
_
>
=
answers
.to_vec
()
.into_iter
()
.map
(|
record
|
types
::
dns
::
Record
::
from
(
record
))
.filter
(|
record
|
match
record
.rdata
{
types
::
dns
::
RData
::
NULL
{
..
}
|
types
::
dns
::
RData
::
DNSSEC
(
_
)
=>
false
,
_
=>
true
,
})
.collect
();
// AXFR response ends with SOA, we remove it so it is not doubled in the response.
records
.pop
();
Json
(
records
)
}
...
...
src/types/dns.rs
View file @
7155c1cc
use
std
::
net
::{
Ipv6Addr
,
Ipv4Addr
};
use
std
::
fmt
;
use
serde
::{
Serialize
,
Deserialize
};
use
trust_dns_client
::
serialize
::
binary
::
BinEncoder
;
use
base64
;
pub
mod
trust_dns_types
{
pub
use
trust_dns_client
::
rr
::
rdata
::{
DNSSECRecordType
,
NULL
,
};
pub
use
trust_dns_client
::
rr
::{
RecordType
,
RData
,
DNSClass
,
Record
};
pub
use
trust_dns_proto
::
rr
::
Name
;
}
use
super
::
trust_dns_types
;
#[derive(Deserialize,
Serialize)]
pub
enum
RecordType
{
...
...
@@ -140,6 +135,7 @@ impl Into<trust_dns_types::RecordType> for RecordType {
#[derive(Deserialize,
Serialize)]
#[serde(tag
=
"Type"
)]
#[serde(rename_all
=
"UPPERCASE"
)]
pub
enum
RData
{
#[serde(rename_all
=
"PascalCase"
)]
A
{
...
...
@@ -149,28 +145,61 @@ pub enum RData {
AAAA
{
address
:
Ipv6Addr
},
ANAME
(
StringName
),
// CAA(CAA),
CNAME
(
StringName
),
#[serde(rename_all
=
"PascalCase"
)]
CAA
{
issuer_critical
:
bool
,
value
:
String
,
property_tag
:
String
,
},
#[serde(rename_all
=
"PascalCase"
)]
CNAME
{
target
:
String
},
// HINFO(HINFO),
// HTTPS(SVCB),
// MX(MX),
#[serde(rename_all
=
"PascalCase"
)]
MX
{
preference
:
u16
,
mail_exchanger
:
String
},
// NAPTR(NAPTR),
NULL
(
NULL
),
NS
(
StringName
),
#[serde(rename_all
=
"PascalCase"
)]
NULL
{
data
:
String
},
#[serde(rename_all
=
"PascalCase"
)]
NS
{
target
:
String
},
// OPENPGPKEY(OPENPGPKEY),
// OPT(OPT),
PTR
(
StringName
),
// SOA(SOA),
#[serde(rename_all
=
"PascalCase"
)]
PTR
{
target
:
String
},
#[serde(rename_all
=
"PascalCase"
)]
SOA
{
master_server_name
:
String
,
maintainer_name
:
String
,
refresh
:
i32
,
retry
:
i32
,
expire
:
i32
,
minimum
:
u32
,
serial
:
u32
},
// SRV(SRV),
// SSHFP(SSHFP),
// SVCB(SVCB),
// TLSA(TLSA),
// TXT(TXT),
// DNSSEC(DNSSECRData),
// TODO: Eventually allow deserialization of DNSSEC records
#[serde(skip)]
DNSSEC
(
trust_dns_types
::
DNSSECRData
),
#[serde(rename_all
=
"PascalCase"
)]
Unknown
{
code
:
u16
,
r
data
:
NULL
,
data
:
String
,
},
// ZERO,
}
...
...
@@ -180,33 +209,84 @@ impl From<trust_dns_types::RData> for RData {
match
rdata
{
trust_dns_types
::
RData
::
A
(
address
)
=>
RData
::
A
{
address
},
trust_dns_types
::
RData
::
AAAA
(
address
)
=>
RData
::
AAAA
{
address
},
_
=>
unimplemented!
()
// Still a draft, no iana number yet, I don't to put something that is not currently supported so that's why NULL and not unknown.
// TODO: probably need better error here, I don't know what to do about that as this would require to change the From for something else.
// (empty data because I'm lazy)
trust_dns_types
::
RData
::
ANAME
(
_
)
=>
RData
::
NULL
{
data
:
String
::
new
()
},
trust_dns_types
::
RData
::
CNAME
(
target
)
=>
RData
::
CNAME
{
target
:
target
.to_utf8
()
},
trust_dns_types
::
RData
::
CAA
(
caa
)
=>
RData
::
CAA
{
issuer_critical
:
caa
.issuer_critical
(),
value
:
format!
(
"{}"
,
CAAValue
(
caa
.value
())),
property_tag
:
caa
.tag
()
.as_str
()
.to_string
(),
},
trust_dns_types
::
RData
::
MX
(
mx
)
=>
RData
::
MX
{
preference
:
mx
.preference
(),
mail_exchanger
:
mx
.exchange
()
.to_utf8
()
},
trust_dns_types
::
RData
::
NULL
(
null
)
=>
RData
::
NULL
{
data
:
base64
::
encode
(
null
.anything
()
.map
(|
data
|
data
.to_vec
())
.unwrap_or_default
())
},
trust_dns_types
::
RData
::
NS
(
target
)
=>
RData
::
NS
{
target
:
target
.to_utf8
()
},
trust_dns_types
::
RData
::
PTR
(
target
)
=>
RData
::
PTR
{
target
:
target
.to_utf8
()
},
trust_dns_types
::
RData
::
SOA
(
soa
)
=>
RData
::
SOA
{
master_server_name
:
soa
.mname
()
.to_utf8
(),
maintainer_name
:
soa
.rname
()
.to_utf8
(),
refresh
:
soa
.refresh
(),
retry
:
soa
.retry
(),
expire
:
soa
.expire
(),
minimum
:
soa
.minimum
(),
serial
:
soa
.serial
()
},
trust_dns_types
::
RData
::
DNSSEC
(
data
)
=>
RData
::
DNSSEC
(
data
),
rdata
=>
{
let
code
=
rdata
.to_record_type
()
.into
();
let
mut
data
=
Vec
::
new
();
let
mut
encoder
=
BinEncoder
::
new
(
&
mut
data
);
rdata
.emit
(
&
mut
encoder
)
.expect
(
"could not encode data"
);
RData
::
Unknown
{
code
,
data
:
base64
::
encode
(
data
),
}
}
}
}
}
struct
CAAValue
<
'a
>
(
&
'a
trust_dns_types
::
caa
::
Value
);
#[derive(Deserialize,
Serialize)]
pub
struct
StringName
(
String
);
impl
From
<
trust_dns_types
::
Name
>
for
StringName
{
fn
from
(
name
:
trust_dns_types
::
Name
)
->
StringName
{
StringName
(
name
.to_utf8
())
}
}
// trust_dns Display implementation panics if no parameters
// Implementation based on caa::emit_value
// Also the quotes are strips to render in JSON
impl
<
'a
>
fmt
::
Display
for
CAAValue
<
'a
>
{
fn
fmt
(
&
self
,
f
:
&
mut
fmt
::
Formatter
<
'_
>
)
->
Result
<
(),
fmt
::
Error
>
{
match
self
.0
{
trust_dns_types
::
caa
::
Value
::
Issuer
(
name
,
parameters
)
=>
{
if
let
Some
(
name
)
=
name
{
write!
(
f
,
"{}"
,
name
)
?
;
}
#[derive(Deserialize,
Serialize)]
pub
struct
NULL
{
pub
anything
:
Option
<
Vec
<
u8
>>
,
}
if
name
.is_none
()
&&
parameters
.is_empty
()
{
write!
(
f
,
";"
)
?
;
}
impl
From
<
trust_dns_types
::
NULL
>
for
NULL
{
fn
from
(
null
:
trust_dns_types
::
NULL
)
->
NULL
{
NULL
{
anything
:
null
.anything
()
.map
(|
e
|
e
.to_vec
())
for
value
in
parameters
{
write!
(
f
,
"; {}"
,
value
)
?
;
}
}
trust_dns_types
::
caa
::
Value
::
Url
(
url
)
=>
write!
(
f
,
"{}"
,
url
)
?
,
trust_dns_types
::
caa
::
Value
::
Unknown
(
v
)
=>
write!
(
f
,
"{:?}"
,
v
)
?
,
}
Ok
(())
}
}
...
...
@@ -237,21 +317,21 @@ impl From<trust_dns_types::DNSClass> for DNSClass {
#[derive(Deserialize,
Serialize)]
pub
struct
Record
{
#[serde(rename
=
"Name"
)]
name
:
String
Name
,
pub
name
:
String
,
//#[serde(rename = "Type")]
//rr_type: RecordType,
#[serde(rename
=
"Class"
)]
dns_class
:
DNSClass
,
pub
dns_class
:
DNSClass
,
#[serde(rename
=
"TTL"
)]
ttl
:
u32
,
pub
ttl
:
u32
,
#[serde(flatten)]
rdata
:
RData
,
pub
rdata
:
RData
,
}
impl
From
<
trust_dns_types
::
Record
>
for
Record
{
fn
from
(
record
:
trust_dns_types
::
Record
)
->
Record
{
Record
{
name
:
StringName
(
record
.name
()
.to_utf8
()
)
,
name
:
record
.name
()
.to_utf8
(),
//rr_type: record.rr_type().into(),
dns_class
:
record
.dns_class
()
.into
(),
ttl
:
record
.ttl
(),
...
...
src/types/mod.rs
View file @
7155c1cc
pub
mod
dns
;
pub
mod
trust_dns_types
{
pub
use
trust_dns_client
::
rr
::
rdata
::{
DNSSECRecordType
,
NULL
,
caa
,
DNSSECRData
};
pub
use
trust_dns_client
::
rr
::{
RecordType
,
RData
,
DNSClass
,
Record
};
pub
use
trust_dns_proto
::
rr
::
Name
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment