wrap some rr fields in flags/enum types with some derived help, add [c]dnskey tag calculation
This commit is contained in:
parent
155b34a17a
commit
f5a6ce44c7
@ -65,6 +65,14 @@ impl DnsTextData for HexShortBlob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::ops::Deref for HexShortBlob {
|
||||||
|
type Target = [u8];
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 16-bit length, uses decimal length + base64 encoding (if length > 0)
|
// 16-bit length, uses decimal length + base64 encoding (if length > 0)
|
||||||
// for text representation.
|
// for text representation.
|
||||||
//
|
//
|
||||||
@ -116,6 +124,14 @@ impl DnsTextData for Base64LongBlob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::ops::Deref for Base64LongBlob {
|
||||||
|
type Target = [u8];
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// No length byte (or restriction), just all data to end of record. uses
|
/// No length byte (or restriction), just all data to end of record. uses
|
||||||
/// base64 encoding for text representation, whitespace allowed, padding
|
/// base64 encoding for text representation, whitespace allowed, padding
|
||||||
/// required.
|
/// required.
|
||||||
@ -154,6 +170,14 @@ impl DnsTextData for Base64RemainingBlob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::ops::Deref for Base64RemainingBlob {
|
||||||
|
type Target = [u8];
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// No length byte (or restriction), just all data to end of record. uses
|
/// No length byte (or restriction), just all data to end of record. uses
|
||||||
/// hex encoding for text representation, whitespace allowed.
|
/// hex encoding for text representation, whitespace allowed.
|
||||||
///
|
///
|
||||||
@ -187,6 +211,14 @@ impl DnsTextData for HexRemainingBlob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::ops::Deref for HexRemainingBlob {
|
||||||
|
type Target = [u8];
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// No length byte (or restriction), just all data to end of record. uses
|
/// No length byte (or restriction), just all data to end of record. uses
|
||||||
/// hex encoding for text representation, whitespace allowed.
|
/// hex encoding for text representation, whitespace allowed.
|
||||||
///
|
///
|
||||||
@ -226,3 +258,11 @@ impl DnsTextData for HexRemainingBlobNotEmpty {
|
|||||||
write!(f, "{}", HEXLOWER_PERMISSIVE_ALLOW_WS.encode(&self.0))
|
write!(f, "{}", HEXLOWER_PERMISSIVE_ALLOW_WS.encode(&self.0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::ops::Deref for HexRemainingBlobNotEmpty {
|
||||||
|
type Target = [u8];
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
9
lib/dnsbox-base/src/common_types/caa.rs
Normal file
9
lib/dnsbox-base/src/common_types/caa.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
use crate::ser::{packet::DnsPacketData, text::DnsTextData};
|
||||||
|
|
||||||
|
#[dnsbox_derive::native_flags(u8)]
|
||||||
|
#[derive(DnsPacketData, DnsTextData)]
|
||||||
|
/// Flags for the CAA RR
|
||||||
|
pub enum CaaFlags {
|
||||||
|
/// Issuer Critical Flag
|
||||||
|
CRITICAL = 0x01, // bit "7"
|
||||||
|
}
|
125
lib/dnsbox-base/src/common_types/dnssec.rs
Normal file
125
lib/dnsbox-base/src/common_types/dnssec.rs
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
use crate::ser::{packet::DnsPacketData, text::DnsTextData};
|
||||||
|
|
||||||
|
// https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
|
||||||
|
#[dnsbox_derive::native_enum(u8)]
|
||||||
|
#[derive(DnsPacketData, DnsTextData)]
|
||||||
|
pub enum DnsSecAlgorithm {
|
||||||
|
/// Delete DS
|
||||||
|
// [RFC4034][RFC4398][RFC8078]
|
||||||
|
DELETE = 0,
|
||||||
|
/// RSA/MD5 (deprecated, see 5)
|
||||||
|
// [RFC3110][RFC4034]
|
||||||
|
RSAMD5 = 1,
|
||||||
|
/// Diffie-Hellman
|
||||||
|
// [RFC2539][proposed standard]
|
||||||
|
DH = 2,
|
||||||
|
/// DSA/SHA1
|
||||||
|
// [RFC3755][proposed standard][RFC2536][proposed standard][Federal Information Processing Standards Publication (FIPS PUB) 186, Digital Signature Standard, 18 May 1994.][Federal Information Processing Standards Publication (FIPS PUB) 180-1, Secure Hash Standard, 17 April 1995. (Supersedes FIPS PUB 180 dated 11 May 1993.)]
|
||||||
|
DSA = 3,
|
||||||
|
|
||||||
|
// Reserved: 4 [RFC6725]
|
||||||
|
|
||||||
|
/// RSA/SHA-1
|
||||||
|
// [RFC3110][RFC4034]
|
||||||
|
RSASHA1 = 5,
|
||||||
|
/// DSA-NSEC3-SHA1
|
||||||
|
// [RFC5155][proposed standard]
|
||||||
|
DSA_NSEC3_SHA1 = 6,
|
||||||
|
/// RSASHA1-NSEC3-SHA1
|
||||||
|
// [RFC5155][proposed standard]
|
||||||
|
RSASHA1_NSEC3_SHA1 = 7,
|
||||||
|
/// RSA/SHA-256
|
||||||
|
// [RFC5702][proposed standard]
|
||||||
|
RSASHA256 = 8,
|
||||||
|
|
||||||
|
// Reserved: 9 [RFC6725]
|
||||||
|
|
||||||
|
/// RSA/SHA-512
|
||||||
|
// [RFC5702][proposed standard]
|
||||||
|
RSASHA512 = 10,
|
||||||
|
|
||||||
|
// Reserved: 11 [RFC6725]
|
||||||
|
|
||||||
|
/// GOST R 34.10-2001
|
||||||
|
// [RFC5933][standards track]
|
||||||
|
ECC_GOST = 12,
|
||||||
|
/// ECDSA Curve P-256 with SHA-256
|
||||||
|
// [RFC6605][standards track]
|
||||||
|
ECDSAP256SHA256 = 13,
|
||||||
|
/// ECDSA Curve P-384 with SHA-384
|
||||||
|
// [RFC6605][standards track]
|
||||||
|
ECDSAP384SHA384 = 14,
|
||||||
|
/// Ed25519
|
||||||
|
// [RFC8080][standards track]
|
||||||
|
ED25519 = 15,
|
||||||
|
/// Ed448
|
||||||
|
// [RFC8080][standards track]
|
||||||
|
ED448 = 16,
|
||||||
|
/// Reserved for Indirect Keys
|
||||||
|
// [RFC4034][proposed standard]
|
||||||
|
INDIRECT = 252,
|
||||||
|
/// private algorithm
|
||||||
|
// [RFC4034]
|
||||||
|
PRIVATEDNS = 253,
|
||||||
|
/// private algorithm OID
|
||||||
|
// [RFC4034]
|
||||||
|
PRIVATEOID = 254,
|
||||||
|
|
||||||
|
// Reserved: 255 [RFC4034][proposed standard]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dnsbox_derive::native_flags(u16)]
|
||||||
|
#[derive(DnsPacketData, DnsTextData)]
|
||||||
|
/// Flags for the DNSKEY RR
|
||||||
|
pub enum DnskeyFlags {
|
||||||
|
ZONE_KEY = 0x0100, // bit "7"
|
||||||
|
/// secure entry point, SEP
|
||||||
|
SECURE_ENTRY_POINT = 0x0001, // bit "15"
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dnsbox_derive::native_enum(u8)]
|
||||||
|
#[derive(DnsPacketData, DnsTextData)]
|
||||||
|
/// Protocol for the DNSKEY RR (only DNSSEC(3) is valid for DNSKEY)
|
||||||
|
pub enum DnskeyProtocol {
|
||||||
|
// reserved: 0x00
|
||||||
|
TLS = 0x01,
|
||||||
|
EMAIL = 0x02,
|
||||||
|
DNSSEC = 0x03,
|
||||||
|
IPSEC = 0x04,
|
||||||
|
ALL = 0xff,
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml
|
||||||
|
#[dnsbox_derive::native_enum(u8)]
|
||||||
|
#[derive(DnsPacketData, DnsTextData)]
|
||||||
|
pub enum DnsSecDigestAlgorithm {
|
||||||
|
// Reserved: 0 [RFC3658]
|
||||||
|
SHA1 = 0x01, // [RFC3658]
|
||||||
|
SHA256 = 0x02, // [RFC4509]
|
||||||
|
GOST_R_34_11_94 = 0x03, // [RFC5933]
|
||||||
|
SHA384 = 0x04, // [RFC6605]
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml
|
||||||
|
#[dnsbox_derive::native_flags(u8)]
|
||||||
|
#[derive(DnsPacketData, DnsTextData)]
|
||||||
|
/// Flags for the NSEC3 RR
|
||||||
|
pub enum Nsec3Flags {
|
||||||
|
OPT_OUT = 0x01, // bit "7"
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml
|
||||||
|
#[dnsbox_derive::native_flags(u8)]
|
||||||
|
#[derive(DnsPacketData, DnsTextData)]
|
||||||
|
/// Flags for the NSEC3PARAM RR
|
||||||
|
pub enum Nsec3ParamFlags {
|
||||||
|
// reserved: Nsec3Flags::OPT_OUT bit "7" (0x01)
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml
|
||||||
|
#[dnsbox_derive::native_enum(u8)]
|
||||||
|
#[derive(DnsPacketData, DnsTextData)]
|
||||||
|
pub enum Nsec3Algorithm {
|
||||||
|
// Reserved: 0 [RFC5155]
|
||||||
|
SHA1 = 0x01, // [RFC5155]
|
||||||
|
}
|
@ -3,20 +3,26 @@ pub mod classes;
|
|||||||
pub mod name;
|
pub mod name;
|
||||||
pub mod text;
|
pub mod text;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
mod caa;
|
||||||
|
mod dnssec;
|
||||||
mod eui;
|
mod eui;
|
||||||
mod nsec;
|
mod nsec;
|
||||||
mod nxt;
|
mod nxt;
|
||||||
mod sig;
|
mod sig;
|
||||||
|
mod sshfp;
|
||||||
mod time;
|
mod time;
|
||||||
mod uri;
|
mod uri;
|
||||||
|
|
||||||
pub use self::binary::{HexShortBlob, Base64LongBlob, Base64RemainingBlob, HexRemainingBlob, HexRemainingBlobNotEmpty};
|
pub use self::binary::{HexShortBlob, Base64LongBlob, Base64RemainingBlob, HexRemainingBlob, HexRemainingBlobNotEmpty};
|
||||||
pub use self::classes::Class;
|
pub use self::classes::Class;
|
||||||
|
pub use self::caa::{CaaFlags};
|
||||||
|
pub use self::dnssec::{DnsSecAlgorithm, DnskeyFlags, DnskeyProtocol, DnsSecDigestAlgorithm, Nsec3Flags, Nsec3ParamFlags, Nsec3Algorithm};
|
||||||
pub use self::eui::{EUI48Addr, EUI64Addr};
|
pub use self::eui::{EUI48Addr, EUI64Addr};
|
||||||
pub use self::name::{DnsName, DnsCanonicalName, DnsCompressedName};
|
pub use self::name::{DnsName, DnsCanonicalName, DnsCompressedName};
|
||||||
pub use self::nsec::{NsecTypeBitmap, NextHashedOwnerName};
|
pub use self::nsec::{NsecTypeBitmap, NextHashedOwnerName};
|
||||||
pub use self::nxt::NxtTypeBitmap;
|
pub use self::nxt::NxtTypeBitmap;
|
||||||
pub use self::sig::OptionalTTL;
|
pub use self::sig::OptionalTTL;
|
||||||
|
pub use self::sshfp::{SshFpAlgorithm, SshFpType};
|
||||||
pub use self::text::{ShortText, LongText, UnquotedShortText, RemainingText};
|
pub use self::text::{ShortText, LongText, UnquotedShortText, RemainingText};
|
||||||
pub use self::time::{Time, TimeStrict, Time48};
|
pub use self::time::{Time, TimeStrict, Time48};
|
||||||
pub use self::types::Type;
|
pub use self::types::Type;
|
||||||
|
25
lib/dnsbox-base/src/common_types/sshfp.rs
Normal file
25
lib/dnsbox-base/src/common_types/sshfp.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
use crate::ser::{packet::DnsPacketData, text::DnsTextData};
|
||||||
|
|
||||||
|
// https://www.iana.org/assignments/dns-sshfp-rr-parameters/dns-sshfp-rr-parameters.xml
|
||||||
|
|
||||||
|
#[dnsbox_derive::native_enum(u8)]
|
||||||
|
#[derive(DnsPacketData, DnsTextData)]
|
||||||
|
pub enum SshFpAlgorithm {
|
||||||
|
// Reserved: 0
|
||||||
|
|
||||||
|
// [RFC4255]
|
||||||
|
RSA = 1,
|
||||||
|
// [RFC4255]
|
||||||
|
DSA = 2,
|
||||||
|
// [RFC6594]
|
||||||
|
ECDSA = 3,
|
||||||
|
// [RFC7479]
|
||||||
|
ED25519 = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dnsbox_derive::native_enum(u8)]
|
||||||
|
#[derive(DnsPacketData, DnsTextData)]
|
||||||
|
pub enum SshFpType {
|
||||||
|
SHA1 = 1,
|
||||||
|
SHA256 = 2,
|
||||||
|
}
|
@ -179,7 +179,7 @@ pub struct NSAP_PTR {
|
|||||||
#[RRClass(ANY)]
|
#[RRClass(ANY)]
|
||||||
pub struct SIG {
|
pub struct SIG {
|
||||||
pub rr_type: Type,
|
pub rr_type: Type,
|
||||||
pub algorithm: u8,
|
pub algorithm: DnsSecAlgorithm,
|
||||||
pub labels: u8,
|
pub labels: u8,
|
||||||
// RFC says this can be omitted in text form if it is the same as
|
// RFC says this can be omitted in text form if it is the same as
|
||||||
// the TTL on the SIG record. not supported to be omitted here
|
// the TTL on the SIG record. not supported to be omitted here
|
||||||
@ -196,8 +196,8 @@ pub struct SIG {
|
|||||||
#[RRClass(ANY)]
|
#[RRClass(ANY)]
|
||||||
pub struct KEY {
|
pub struct KEY {
|
||||||
pub flags: u16,
|
pub flags: u16,
|
||||||
pub protocol: u8,
|
pub protocol: DnskeyProtocol,
|
||||||
pub algorithm: u8,
|
pub algorithm: DnsSecAlgorithm,
|
||||||
pub public_key: Base64RemainingBlob,
|
pub public_key: Base64RemainingBlob,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,9 +274,10 @@ pub struct KX {
|
|||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
// #[RRClass(?)]
|
// #[RRClass(?)]
|
||||||
pub struct CERT {
|
pub struct CERT {
|
||||||
|
// https://www.iana.org/assignments/cert-rr-types/cert-rr-types.xhtml
|
||||||
pub cert_type: u16,
|
pub cert_type: u16,
|
||||||
pub key_tag: u16,
|
pub key_tag: u16,
|
||||||
pub algorithm: u8,
|
pub algorithm: DnsSecAlgorithm,
|
||||||
pub certificate: Base64RemainingBlob,
|
pub certificate: Base64RemainingBlob,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,16 +305,16 @@ pub struct DNAME {
|
|||||||
#[RRClass(ANY)]
|
#[RRClass(ANY)]
|
||||||
pub struct DS {
|
pub struct DS {
|
||||||
pub key_tag: u16,
|
pub key_tag: u16,
|
||||||
pub algorithm: u8,
|
pub algorithm: DnsSecAlgorithm,
|
||||||
pub digest_type: u8,
|
pub digest_type: DnsSecDigestAlgorithm,
|
||||||
pub digest: HexRemainingBlob,
|
pub digest: HexRemainingBlob,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
// #[RRClass(?)]
|
// #[RRClass(?)]
|
||||||
pub struct SSHFP {
|
pub struct SSHFP {
|
||||||
pub algorithm: u8,
|
pub algorithm: SshFpAlgorithm,
|
||||||
pub fingerprint_type: u8,
|
pub fingerprint_type: SshFpType,
|
||||||
// RFC 4255 doesn't specify whether whitespace is allowed.
|
// RFC 4255 doesn't specify whether whitespace is allowed.
|
||||||
// `HexRemainingBlob` allows whitespace.
|
// `HexRemainingBlob` allows whitespace.
|
||||||
pub fingerprint: HexRemainingBlob,
|
pub fingerprint: HexRemainingBlob,
|
||||||
@ -325,7 +326,7 @@ pub use super::weird_structs::IPSECKEY;
|
|||||||
#[RRClass(ANY)]
|
#[RRClass(ANY)]
|
||||||
pub struct RRSIG {
|
pub struct RRSIG {
|
||||||
pub rr_type: Type,
|
pub rr_type: Type,
|
||||||
pub algorithm: u8,
|
pub algorithm: DnsSecAlgorithm,
|
||||||
pub labels: u8,
|
pub labels: u8,
|
||||||
pub original_ttl: u32,
|
pub original_ttl: u32,
|
||||||
pub signature_expiration: Time,
|
pub signature_expiration: Time,
|
||||||
@ -345,12 +346,55 @@ pub struct NSEC {
|
|||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
#[RRClass(ANY)]
|
#[RRClass(ANY)]
|
||||||
pub struct DNSKEY {
|
pub struct DNSKEY {
|
||||||
pub flags: u16,
|
pub flags: DnskeyFlags,
|
||||||
pub protocol: u8,
|
pub protocol: DnskeyProtocol, // should always be DNSSEC (3) according to RFC 4034
|
||||||
pub algorithm: u8,
|
pub algorithm: DnsSecAlgorithm,
|
||||||
pub public_key: Base64RemainingBlob,
|
pub public_key: Base64RemainingBlob,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DNSKEY {
|
||||||
|
fn alg1_tag(&self) -> u16 {
|
||||||
|
let key: &[u8] = &self.public_key;
|
||||||
|
if key.is_empty() { return 0; } // not enough data
|
||||||
|
let pkey;
|
||||||
|
if 0 == key[0] {
|
||||||
|
// two-byte length encoding of exponent
|
||||||
|
if key.len() < 3 { return 0; } // not enough data
|
||||||
|
let explen = ((key[1] as u16) << 8) + (key[2] as u16);
|
||||||
|
if explen < 256 { return 0; } // should have used shorter length encoding
|
||||||
|
if key.len() < 3 + (explen as usize) { return 0; } // not enough data
|
||||||
|
pkey = &key[3 + (explen as usize)..];
|
||||||
|
} else {
|
||||||
|
// one-byte length encoding of exponent
|
||||||
|
let explen = key[0];
|
||||||
|
if key.len() < 1 + (explen as usize) { return 0; } // not enough data
|
||||||
|
pkey = &key[1 + (explen as usize)..];
|
||||||
|
}
|
||||||
|
if pkey.len() < 3 { return 0; } // not enough data
|
||||||
|
((pkey[pkey.len() - 3] as u16) << 8) + (pkey[pkey.len() - 3] as u16)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// calculate key tag
|
||||||
|
pub fn tag(&self) -> u16 {
|
||||||
|
if self.algorithm == DnsSecAlgorithm::RSAMD5 { return self.alg1_tag(); }
|
||||||
|
|
||||||
|
let mut sum = 0u32;
|
||||||
|
|
||||||
|
sum += self.flags.0 as u32;
|
||||||
|
sum += (self.protocol.0 as u32) << 8;
|
||||||
|
sum += self.algorithm.0 as u32;
|
||||||
|
|
||||||
|
let key: &[u8] = &self.public_key;
|
||||||
|
for i in 0..key.len() {
|
||||||
|
let v = key[i] as u32;
|
||||||
|
let v = if 0 == i & 1 { v << 8 } else { v };
|
||||||
|
sum = sum.wrapping_add(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
sum.wrapping_add(sum >> 16) as u16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
#[RRClass(IN)]
|
#[RRClass(IN)]
|
||||||
pub struct DHCID {
|
pub struct DHCID {
|
||||||
@ -360,8 +404,8 @@ pub struct DHCID {
|
|||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
#[RRClass(ANY)]
|
#[RRClass(ANY)]
|
||||||
pub struct NSEC3 {
|
pub struct NSEC3 {
|
||||||
pub hash_algorithm: u8,
|
pub hash_algorithm: Nsec3Algorithm,
|
||||||
pub flags: u8,
|
pub flags: Nsec3Flags,
|
||||||
pub iterations: u16,
|
pub iterations: u16,
|
||||||
pub salt: HexShortBlob,
|
pub salt: HexShortBlob,
|
||||||
pub next_hashed: NextHashedOwnerName,
|
pub next_hashed: NextHashedOwnerName,
|
||||||
@ -371,8 +415,8 @@ pub struct NSEC3 {
|
|||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
#[RRClass(ANY)]
|
#[RRClass(ANY)]
|
||||||
pub struct NSEC3PARAM {
|
pub struct NSEC3PARAM {
|
||||||
pub hash_algorithm: u8,
|
pub hash_algorithm: Nsec3Algorithm,
|
||||||
pub flags: u8,
|
pub flags: Nsec3ParamFlags,
|
||||||
pub iterations: u16,
|
pub iterations: u16,
|
||||||
pub salt: HexShortBlob,
|
pub salt: HexShortBlob,
|
||||||
}
|
}
|
||||||
@ -413,7 +457,7 @@ pub struct NINFO {
|
|||||||
pub struct RKEY {
|
pub struct RKEY {
|
||||||
pub flags: u16,
|
pub flags: u16,
|
||||||
pub protocol: u8,
|
pub protocol: u8,
|
||||||
pub algorithm: u8,
|
pub algorithm: DnsSecAlgorithm,
|
||||||
pub public_key: Base64RemainingBlob,
|
pub public_key: Base64RemainingBlob,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,20 +469,31 @@ pub struct RKEY {
|
|||||||
#[RRClass(ANY)]
|
#[RRClass(ANY)]
|
||||||
pub struct CDS {
|
pub struct CDS {
|
||||||
pub key_tag: u16,
|
pub key_tag: u16,
|
||||||
pub algorithm: u8,
|
pub algorithm: DnsSecAlgorithm,
|
||||||
pub digest_type: u8,
|
pub digest_type: DnsSecDigestAlgorithm,
|
||||||
pub digest: HexRemainingBlob,
|
pub digest: HexRemainingBlob,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
#[RRClass(ANY)]
|
#[RRClass(ANY)]
|
||||||
pub struct CDNSKEY {
|
pub struct CDNSKEY {
|
||||||
pub flags: u16,
|
pub flags: DnskeyFlags,
|
||||||
pub protocol: u8,
|
pub protocol: DnskeyProtocol,
|
||||||
pub algorithm: u8,
|
pub algorithm: DnsSecAlgorithm,
|
||||||
pub public_key: Base64RemainingBlob,
|
pub public_key: Base64RemainingBlob,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CDNSKEY {
|
||||||
|
pub fn tag(&self) -> u16 {
|
||||||
|
DNSKEY {
|
||||||
|
flags: self.flags,
|
||||||
|
protocol: self.protocol,
|
||||||
|
algorithm: self.algorithm,
|
||||||
|
public_key: self.public_key.clone(),
|
||||||
|
}.tag()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
#[RRClass(ANY)]
|
#[RRClass(ANY)]
|
||||||
pub struct OPENPGPKEY {
|
pub struct OPENPGPKEY {
|
||||||
@ -545,7 +600,7 @@ pub struct URI {
|
|||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
// #[RRClass(?)]
|
// #[RRClass(?)]
|
||||||
pub struct CAA {
|
pub struct CAA {
|
||||||
pub flags: u8,
|
pub flags: CaaFlags,
|
||||||
pub tag: UnquotedShortText,
|
pub tag: UnquotedShortText,
|
||||||
pub value: RemainingText,
|
pub value: RemainingText,
|
||||||
}
|
}
|
||||||
@ -559,8 +614,8 @@ pub struct CAA {
|
|||||||
#[RRClass(ANY)]
|
#[RRClass(ANY)]
|
||||||
pub struct DLV {
|
pub struct DLV {
|
||||||
pub key_tag: u16,
|
pub key_tag: u16,
|
||||||
pub algorithm: u8,
|
pub algorithm: DnsSecAlgorithm,
|
||||||
pub digest_type: u8,
|
pub digest_type: DnsSecDigestAlgorithm,
|
||||||
pub digest: HexRemainingBlob,
|
pub digest: HexRemainingBlob,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,11 +9,14 @@ extern crate proc_macro2;
|
|||||||
mod rrdata;
|
mod rrdata;
|
||||||
mod dns_packet_data;
|
mod dns_packet_data;
|
||||||
mod dns_text_data;
|
mod dns_text_data;
|
||||||
|
mod native_enum;
|
||||||
|
mod native_flags;
|
||||||
|
|
||||||
decl_derive!([DnsPacketData] => dns_packet_data::derive);
|
decl_derive!([DnsPacketData] => dns_packet_data::derive);
|
||||||
decl_derive!([DnsTextData] => dns_text_data::derive);
|
decl_derive!([DnsTextData] => dns_text_data::derive);
|
||||||
decl_derive!([RRData, attributes(RRTypeName, RRClass)] => rrdata::rrdata_derive);
|
decl_derive!([RRData, attributes(RRTypeName, RRClass)] => rrdata::rrdata_derive);
|
||||||
|
decl_attribute!([native_enum] => native_enum::attribute_native_enum);
|
||||||
|
decl_attribute!([native_flags] => native_flags::attribute_native_flags);
|
||||||
|
|
||||||
fn attr_get_single_list_arg(attr_meta: &syn::Meta) -> proc_macro2::TokenStream {
|
fn attr_get_single_list_arg(attr_meta: &syn::Meta) -> proc_macro2::TokenStream {
|
||||||
match attr_meta {
|
match attr_meta {
|
||||||
|
88
lib/dnsbox-derive/src/native_enum.rs
Normal file
88
lib/dnsbox-derive/src/native_enum.rs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
use proc_macro2::TokenStream;
|
||||||
|
|
||||||
|
pub fn attribute_native_enum(
|
||||||
|
native_type: TokenStream,
|
||||||
|
structure: synstructure::Structure,
|
||||||
|
) -> TokenStream {
|
||||||
|
let ast = structure.ast();
|
||||||
|
let in_attrs = ast.attrs.iter().map(|a| quote!{#a}).collect::<TokenStream>();
|
||||||
|
let in_vis = &ast.vis;
|
||||||
|
let name = &ast.ident;
|
||||||
|
|
||||||
|
let known_name = syn::Ident::new(&format!("{}Known", name), proc_macro2::Span::call_site());
|
||||||
|
|
||||||
|
let enumdata = match &ast.data {
|
||||||
|
syn::Data::Enum(de) => de,
|
||||||
|
_ => panic!("not an enum"),
|
||||||
|
};
|
||||||
|
let known_enum;
|
||||||
|
|
||||||
|
{
|
||||||
|
let variants = &enumdata.variants;
|
||||||
|
let doc_str = format!("Known enum variants of [`{}`]\n\n[`{}`]: struct.{}.html\n", name, name, name);
|
||||||
|
known_enum = quote! {
|
||||||
|
#[doc = #doc_str]
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||||
|
#[repr(#native_type)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#in_vis enum #known_name {
|
||||||
|
#variants
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut consts = TokenStream::new();
|
||||||
|
let mut convert = TokenStream::new();
|
||||||
|
for variant in &enumdata.variants {
|
||||||
|
let variant_attrs = variant.attrs.iter().map(|a| quote!{#a}).collect::<TokenStream>();
|
||||||
|
let disc_name = &variant.ident;
|
||||||
|
let disc = variant.discriminant.as_ref().map(|(_, d)| quote!{#d}).unwrap_or_else(|| quote!{
|
||||||
|
#known_name::#disc_name as #native_type
|
||||||
|
});
|
||||||
|
consts.extend(quote! {
|
||||||
|
#variant_attrs
|
||||||
|
pub const #disc_name: Self = #name(#disc);
|
||||||
|
});
|
||||||
|
convert.extend(quote! {
|
||||||
|
Self::#disc_name => #known_name::#disc_name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#known_enum
|
||||||
|
|
||||||
|
#in_attrs
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
|
#in_vis struct #name(pub #native_type);
|
||||||
|
|
||||||
|
impl #name {
|
||||||
|
#consts
|
||||||
|
|
||||||
|
/// Try converting to known enum values
|
||||||
|
pub fn into_known(self) -> Option<#known_name> {
|
||||||
|
Some(
|
||||||
|
#[allow(unreachable_patterns)]
|
||||||
|
match self {
|
||||||
|
#convert
|
||||||
|
_ => return None,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::fmt::Debug for #name {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||||
|
match self.into_known() {
|
||||||
|
Some(v) => v.fmt(f),
|
||||||
|
None => f.debug_tuple(stringify!(#name)).field(&self.0).finish(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<#known_name> for #name {
|
||||||
|
fn from(v: #known_name) -> Self {
|
||||||
|
#name(v as #native_type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
136
lib/dnsbox-derive/src/native_flags.rs
Normal file
136
lib/dnsbox-derive/src/native_flags.rs
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
use proc_macro2::TokenStream;
|
||||||
|
|
||||||
|
pub fn attribute_native_flags(
|
||||||
|
native_type: TokenStream,
|
||||||
|
structure: synstructure::Structure,
|
||||||
|
) -> TokenStream {
|
||||||
|
let ast = structure.ast();
|
||||||
|
let in_attrs = ast.attrs.iter().map(|a| quote!{#a}).collect::<TokenStream>();
|
||||||
|
let in_vis = &ast.vis;
|
||||||
|
let name = &ast.ident;
|
||||||
|
|
||||||
|
let hidden_impl_mod = syn::Ident::new(&format!("_{}_hidden_native_flags", name), proc_macro2::Span::call_site());
|
||||||
|
|
||||||
|
let enumdata = match &ast.data {
|
||||||
|
syn::Data::Enum(de) => de,
|
||||||
|
_ => panic!("not an enum"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut consts = TokenStream::new();
|
||||||
|
let mut known_mask = TokenStream::new();
|
||||||
|
let mut dbg = TokenStream::new();
|
||||||
|
for variant in &enumdata.variants {
|
||||||
|
let variant_attrs = variant.attrs.iter().map(|a| quote!{#a}).collect::<TokenStream>();
|
||||||
|
let disc_name = &variant.ident;
|
||||||
|
let disc = variant.discriminant.as_ref().map(|(_, d)| d).expect("all variants need explicit bitmask discriminants");
|
||||||
|
consts.extend(quote! {
|
||||||
|
#variant_attrs
|
||||||
|
pub const #disc_name: Flag = Flag { mask: #disc };
|
||||||
|
});
|
||||||
|
known_mask.extend(quote!{
|
||||||
|
| #disc
|
||||||
|
});
|
||||||
|
dbg.extend(quote! {
|
||||||
|
if self & Self::#disc_name {
|
||||||
|
if !first { f.write_str(" | ")?; }
|
||||||
|
first = false;
|
||||||
|
f.write_str(stringify!(#disc_name))?;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let bitops = quote! {
|
||||||
|
impl core::ops::BitAnd<Flag> for super::#name {
|
||||||
|
type Output = bool;
|
||||||
|
|
||||||
|
fn bitand(self, rhs: Flag) -> Self::Output {
|
||||||
|
rhs.mask == self.0 & rhs.mask
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::ops::BitAnd<Flag> for &super::#name {
|
||||||
|
type Output = bool;
|
||||||
|
|
||||||
|
fn bitand(self, rhs: Flag) -> Self::Output {
|
||||||
|
rhs.mask == self.0 & rhs.mask
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::ops::BitOr for Flag {
|
||||||
|
type Output = super::#name;
|
||||||
|
|
||||||
|
fn bitor(self, rhs: Flag) -> Self::Output {
|
||||||
|
super::#name(self.mask | rhs.mask)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::ops::BitOr<Flag> for super::#name {
|
||||||
|
type Output = super::#name;
|
||||||
|
|
||||||
|
fn bitor(self, rhs: Flag) -> Self::Output {
|
||||||
|
super::#name(self.0 | rhs.mask)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::ops::BitOr<super::#name> for Flag {
|
||||||
|
type Output = super::#name;
|
||||||
|
|
||||||
|
fn bitor(self, rhs: super::#name) -> Self::Output {
|
||||||
|
super::#name(self.mask | rhs.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#in_attrs
|
||||||
|
///
|
||||||
|
/// The `Flag` constants can be used to check if a flag is set
|
||||||
|
/// by using bitwise and: `flags & flag`.
|
||||||
|
///
|
||||||
|
/// They can be converted to and combined with bitwise or to set
|
||||||
|
/// flags. Their bitmask is available as public struct member
|
||||||
|
/// `mask`.
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
|
#in_vis struct #name(pub #native_type);
|
||||||
|
|
||||||
|
mod #hidden_impl_mod {
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||||
|
pub struct Flag {
|
||||||
|
pub mask: #native_type,
|
||||||
|
}
|
||||||
|
|
||||||
|
const known_mask: #native_type = 0 #known_mask;
|
||||||
|
|
||||||
|
impl super::#name {
|
||||||
|
pub fn new_flag(mask: #native_type) -> Flag {
|
||||||
|
Flag { mask }
|
||||||
|
}
|
||||||
|
|
||||||
|
#consts
|
||||||
|
}
|
||||||
|
|
||||||
|
#bitops
|
||||||
|
|
||||||
|
impl From<Flag> for super::#name {
|
||||||
|
fn from(v: Flag) -> Self {
|
||||||
|
Self(v.mask)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::fmt::Debug for super::#name {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||||
|
let mut first = true;
|
||||||
|
let unknown_bits = self.0 & !known_mask;
|
||||||
|
#dbg
|
||||||
|
if unknown_bits != 0 {
|
||||||
|
if !first { f.write_str(" | ")?; }
|
||||||
|
write!(f, "unknown(0x{:x})", unknown_bits)?;
|
||||||
|
} else if first {
|
||||||
|
f.write_str("(empty)")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user