
9 changed files with 513 additions and 26 deletions
@ -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"
|
||||
} |
@ -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]
|
||||
} |
@ -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, |
||||
} |
@ -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) |
||||
} |
||||
} |
||||
} |
||||
} |
@ -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