better docs or something like that

This commit is contained in:
chayleaf 2024-08-13 19:08:57 +07:00
parent 8a106c66a2
commit e0f6421800
Signed by: chayleaf
GPG key ID: 78171AD46227E68E
14 changed files with 700 additions and 571 deletions

9
Cargo.lock generated
View file

@ -78,7 +78,7 @@ dependencies = [
"serde",
"serde_json",
"smallvec",
"unbound-mod",
"unbound",
]
[[package]]
@ -363,12 +363,17 @@ dependencies = [
]
[[package]]
name = "unbound-mod"
name = "unbound"
version = "0.1.0"
dependencies = [
"ctor",
"unbound-sys",
]
[[package]]
name = "unbound-sys"
version = "0.1.0"
[[package]]
name = "unicode-ident"
version = "1.0.12"

View file

@ -1,3 +1,3 @@
[workspace]
members = ["example", "unbound-mod"]
members = ["example", "unbound", "unbound-sys"]
resolver = "2"

View file

@ -21,4 +21,4 @@ radix_trie = "0.2.1"
serde = { version = "1.0.205", features = ["derive"] }
serde_json = "1.0.122"
smallvec = "1.13.2"
unbound-mod = { path = "../unbound-mod" }
unbound = { path = "../unbound" }

View file

@ -23,12 +23,9 @@ use smallvec::SmallVec;
use domain_tree::PrefixSet;
use nftables::{nftables_thread, NftData};
use unbound_mod::{
unbound::{
rr_class, rr_type, ModuleEnvMut, ModuleEvent, ModuleExtState, ModuleQstateMut,
OutboundEntryMut, ReplyInfo,
},
UnboundMod,
use unbound::{
module::UnboundMod, rr_class, rr_type, set_module, ModuleEnvMut, ModuleEvent, ModuleExtState,
ModuleQstateMut, OutboundEntryMut, ReplyInfo,
};
mod domain_tree;
@ -37,7 +34,7 @@ mod nftables;
type Domain = SmallVec<[u8; 32]>;
type DomainSeg = SmallVec<[u8; 16]>;
unbound_mod::set_module!(ExampleMod);
set_module!(ExampleMod);
struct IpNetDeser(IpNet);
struct IpNetVisitor;
@ -728,7 +725,7 @@ impl UnboundMod for ExampleMod {
}
}
let info = qstate.qinfo();
let name = info.qname().to_bytes();
let name = info.qname().unwrap().to_bytes();
let split_domain = unwire_domain(name);
if let Some(val) = self.run_commands(&split_domain) {
return Some(val);
@ -756,7 +753,7 @@ mod test {
use smallvec::smallvec;
use super::{ignore, ExampleMod, IpCacheKey, IpNetDeser, DATA_PREFIX};
use unbound_mod::unbound::ModuleExtState;
use unbound::ModuleExtState;
#[test]
fn test() {

View file

@ -24,7 +24,12 @@
opts+=(--allowlist-file ".*/$file")
done
bindgen --no-layout-tests "''${opts[@]}" dummy.h -- -I "$PWD" $(grep ^CPPFLAGS= config.log | sed "s/.*='//;s/'//" | head -c-1 && grep ^CFLAGS= config.log | sed "s/.*-pthread//;s/'//") > "$out"
bindgen \
--raw-line "#![allow(non_camel_case_types, non_snake_case, non_upper_case_globals, clippy::all)]" \
--no-layout-tests "''${opts[@]}" dummy.h \
-- -I "$PWD" \
$(grep ^CPPFLAGS= config.log | sed "s/.*='//;s/'//" | head -c-1 && grep ^CFLAGS= config.log | sed "s/.*-pthread//;s/'//") \
>"$out"
'';
});
unbound-mod = let
@ -36,7 +41,7 @@
cargoExtraArgs = "--package example";
postPatch = ''
ls -la
cp ${bindings} unbound-mod/src/bindings.rs
cp ${bindings} unbound-sys/src/lib.rs
'';
src = nixpkgs.lib.cleanSourceWith {
src = ./.;

View file

@ -1,197 +0,0 @@
#![allow(clippy::type_complexity, clippy::missing_safety_doc)]
use std::panic::{RefUnwindSafe, UnwindSafe};
use unbound::ModuleExtState;
#[allow(
dead_code,
improper_ctypes,
non_camel_case_types,
non_snake_case,
non_upper_case_globals,
unused_imports,
clippy::all,
clippy::nursery,
clippy::pedantic
)]
#[doc(hidden)]
pub mod bindings;
mod combine;
mod exports;
pub mod unbound;
pub use bindings as sys;
#[doc(hidden)]
pub use ctor;
#[macro_export]
macro_rules! set_module {
($mod:ty) => {
use unbound_mod::ctor::ctor;
#[ctor]
fn _internal_module_setup() {
unbound_mod::set_unbound_mod::<$mod>();
}
};
}
pub trait UnboundMod: Send + Sync + Sized + RefUnwindSafe + UnwindSafe {
type EnvData;
type QstateData;
#[allow(clippy::result_unit_err)]
fn init(_env: &mut unbound::ModuleEnvMut<Self::EnvData>) -> Result<Self, ()> {
Err(())
}
fn deinit(self, _env: &mut unbound::ModuleEnvMut<Self::EnvData>) {}
fn operate(
&self,
_qstate: &mut unbound::ModuleQstateMut<Self::QstateData>,
_event: unbound::ModuleEvent,
_entry: Option<&mut unbound::OutboundEntryMut>,
) -> Option<ModuleExtState> {
Some(ModuleExtState::Finished)
}
fn inform_super(
&self,
_qstate: &mut unbound::ModuleQstateMut<Self::QstateData>,
_super_qstate: &mut unbound::ModuleQstateMut<::std::ffi::c_void>,
) {
}
fn clear(&self, _qstate: &mut unbound::ModuleQstateMut<Self::QstateData>) {}
fn get_mem(&self, _env: &mut unbound::ModuleEnvMut<Self::EnvData>) -> usize {
0
}
}
/// # Safety
///
/// Be safe
unsafe trait SealedUnboundMod: Send + Sync {
unsafe fn internal_deinit(
self: Box<Self>,
env: *mut bindings::module_env,
id: ::std::os::raw::c_int,
);
unsafe fn internal_operate(
&self,
qstate: *mut bindings::module_qstate,
event: bindings::module_ev,
id: ::std::os::raw::c_int,
entry: *mut bindings::outbound_entry,
);
unsafe fn internal_inform_super(
&self,
qstate: *mut bindings::module_qstate,
id: ::std::os::raw::c_int,
super_qstate: *mut bindings::module_qstate,
);
unsafe fn internal_clear(
&self,
qstate: *mut bindings::module_qstate,
id: ::std::os::raw::c_int,
);
unsafe fn internal_get_mem(
&self,
env: *mut bindings::module_env,
id: ::std::os::raw::c_int,
) -> usize;
}
unsafe impl<T: UnboundMod> SealedUnboundMod for T {
unsafe fn internal_deinit(
self: Box<Self>,
env: *mut bindings::module_env,
id: ::std::os::raw::c_int,
) {
std::panic::catch_unwind(|| {
self.deinit(&mut unbound::ModuleEnvMut::from_raw(env, id).unwrap());
})
.unwrap_or(());
}
unsafe fn internal_operate(
&self,
qstate: *mut bindings::module_qstate,
event: bindings::module_ev,
id: ::std::os::raw::c_int,
entry: *mut bindings::outbound_entry,
) {
std::panic::catch_unwind(|| {
if let Some(ext_state) = self.operate(
&mut unbound::ModuleQstateMut::from_raw(qstate, id).unwrap(),
event.into(),
unbound::OutboundEntryMut::from_raw(entry).as_mut(),
) {
if let Some(id) = unbound::check_id(id) {
(*qstate).ext_state[id] = ext_state as bindings::module_ext_state;
}
}
})
.unwrap_or(());
}
unsafe fn internal_inform_super(
&self,
qstate: *mut bindings::module_qstate,
id: ::std::os::raw::c_int,
super_qstate: *mut bindings::module_qstate,
) {
std::panic::catch_unwind(|| {
self.inform_super(
&mut unbound::ModuleQstateMut::from_raw(qstate, id).unwrap(),
&mut unbound::ModuleQstateMut::from_raw(super_qstate, -1).unwrap(),
);
})
.unwrap_or(());
}
unsafe fn internal_clear(
&self,
qstate: *mut bindings::module_qstate,
id: ::std::os::raw::c_int,
) {
std::panic::catch_unwind(|| {
self.clear(&mut unbound::ModuleQstateMut::from_raw(qstate, id).unwrap());
})
.unwrap_or(());
}
unsafe fn internal_get_mem(
&self,
env: *mut bindings::module_env,
id: ::std::os::raw::c_int,
) -> usize {
std::panic::catch_unwind(|| {
self.get_mem(&mut unbound::ModuleEnvMut::from_raw(env, id).unwrap())
})
.unwrap_or(0)
}
}
static mut MODULE: std::sync::OnceLock<Box<dyn SealedUnboundMod>> = std::sync::OnceLock::new();
unsafe fn module() -> Option<&'static dyn SealedUnboundMod> {
MODULE.get().map(|x| &**x)
}
static mut MODULE_FACTORY: std::sync::OnceLock<
Box<
dyn Sync
+ Send
+ FnOnce(*mut bindings::module_env, ::std::os::raw::c_int) -> ::std::os::raw::c_int,
>,
> = std::sync::OnceLock::new();
pub fn set_unbound_mod<T: 'static + UnboundMod>() {
unsafe {
MODULE_FACTORY
.set(Box::new(|env, id| {
std::panic::catch_unwind(|| {
unbound::ModuleEnvMut::from_raw(env, id)
.and_then(|mut env| T::init(&mut env).ok())
.map_or(0, |module| {
MODULE.set(Box::new(module)).map_err(|_| ()).unwrap();
1
})
})
.unwrap_or(0)
}))
.map_err(|_| "set_unbound_mod failed")
.unwrap();
}
}

View file

@ -1,9 +1,8 @@
[package]
name = "unbound-mod"
name = "unbound-sys"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
ctor = "0.2.8"

View file

@ -1,5 +1,12 @@
/* automatically generated by rust-bindgen 0.69.4 */
#![allow(
non_camel_case_types,
non_snake_case,
non_upper_case_globals,
clippy::all
)]
#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct __BindgenBitfieldUnit<Storage> {
@ -1946,222 +1953,6 @@ extern "C" {
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct serviced_query {
_unused: [u8; 0],
}
#[doc = " The outbound list. This structure is part of the module specific query\n state."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct outbound_list {
#[doc = " The linked list of outbound query entries."]
pub first: *mut outbound_entry,
}
#[doc = " Outbound list entry. A serviced query sent by a module processing the\n query from the qstate. Double linked list to aid removal."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct outbound_entry {
#[doc = " next in list"]
pub next: *mut outbound_entry,
#[doc = " prev in list"]
pub prev: *mut outbound_entry,
#[doc = " The query that was sent out"]
pub qsent: *mut serviced_query,
#[doc = " the module query state that sent it"]
pub qstate: *mut module_qstate,
}
extern "C" {
#[doc = " Init the user allocated outbound list structure\n @param list: the list structure."]
pub fn outbound_list_init(list: *mut outbound_list);
}
extern "C" {
#[doc = " Clear the user owner outbound list structure.\n Deletes serviced queries.\n @param list: the list structure. It is cleared, but the list struct itself\n \tis callers responsibility to delete."]
pub fn outbound_list_clear(list: *mut outbound_list);
}
extern "C" {
#[doc = " Insert new entry into the list. Caller must allocate the entry with malloc.\n qstate and qsent are set by caller.\n @param list: the list to add to.\n @param e: entry to add, it is only half initialised at call start, fully\n\tinitialised at call end."]
pub fn outbound_list_insert(list: *mut outbound_list, e: *mut outbound_entry);
}
extern "C" {
#[doc = " Remove an entry from the list, and deletes it.\n Deletes serviced query in the entry.\n @param list: the list to remove from.\n @param e: the entry to remove."]
pub fn outbound_list_remove(list: *mut outbound_list, e: *mut outbound_entry);
}
extern "C" {
#[doc = " Get the module function block.\n @return: function block with function pointers to module methods."]
pub fn dynlibmod_get_funcblock() -> *mut module_func_block;
}
extern "C" {
#[doc = " dynlib module init"]
pub fn dynlibmod_init(env: *mut module_env, id: ::std::os::raw::c_int)
-> ::std::os::raw::c_int;
}
extern "C" {
#[doc = " dynlib module deinit"]
pub fn dynlibmod_deinit(env: *mut module_env, id: ::std::os::raw::c_int);
}
extern "C" {
#[doc = " dynlib module operate on a query"]
pub fn dynlibmod_operate(
qstate: *mut module_qstate,
event: module_ev,
id: ::std::os::raw::c_int,
outbound: *mut outbound_entry,
);
}
extern "C" {
#[doc = " dynlib module"]
pub fn dynlibmod_inform_super(
qstate: *mut module_qstate,
id: ::std::os::raw::c_int,
super_: *mut module_qstate,
);
}
extern "C" {
#[doc = " dynlib module cleanup query state"]
pub fn dynlibmod_clear(qstate: *mut module_qstate, id: ::std::os::raw::c_int);
}
extern "C" {
#[doc = " dynlib module alloc size routine"]
pub fn dynlibmod_get_mem(env: *mut module_env, id: ::std::os::raw::c_int) -> usize;
}
extern "C" {
pub fn dynlib_inplace_cb_reply_generic(
qinfo: *mut query_info,
qstate: *mut module_qstate,
rep: *mut reply_info,
rcode: ::std::os::raw::c_int,
edns: *mut edns_data,
opt_list_out: *mut *mut edns_option,
repinfo: *mut comm_reply,
region: *mut regional,
start_time: *mut timeval,
id: ::std::os::raw::c_int,
callback: *mut ::std::os::raw::c_void,
) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn dynlib_inplace_cb_query_generic(
qinfo: *mut query_info,
flags: u16,
qstate: *mut module_qstate,
addr: *mut sockaddr_storage,
addrlen: socklen_t,
zone: *mut u8,
zonelen: usize,
region: *mut regional,
id: ::std::os::raw::c_int,
callback: *mut ::std::os::raw::c_void,
) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn dynlib_inplace_cb_edns_back_parsed(
qstate: *mut module_qstate,
id: ::std::os::raw::c_int,
cb_args: *mut ::std::os::raw::c_void,
) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn dynlib_inplace_cb_query_response(
qstate: *mut module_qstate,
response: *mut dns_msg,
id: ::std::os::raw::c_int,
cb_args: *mut ::std::os::raw::c_void,
) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn inplace_cb_register_wrapped(
cb: *mut ::std::os::raw::c_void,
type_: inplace_cb_list_type,
cbarg: *mut ::std::os::raw::c_void,
env: *mut module_env,
id: ::std::os::raw::c_int,
) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn inplace_cb_delete_wrapped(
env: *mut module_env,
type_: inplace_cb_list_type,
id: ::std::os::raw::c_int,
);
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct cb_pair {
pub cb: *mut ::std::os::raw::c_void,
pub cb_arg: *mut ::std::os::raw::c_void,
}
#[doc = " Global state for the module."]
pub type func_init_t = ::std::option::Option<
unsafe extern "C" fn(
arg1: *mut module_env,
arg2: ::std::os::raw::c_int,
) -> ::std::os::raw::c_int,
>;
pub type func_deinit_t =
::std::option::Option<unsafe extern "C" fn(arg1: *mut module_env, arg2: ::std::os::raw::c_int)>;
pub type func_operate_t = ::std::option::Option<
unsafe extern "C" fn(
arg1: *mut module_qstate,
arg2: module_ev,
arg3: ::std::os::raw::c_int,
arg4: *mut outbound_entry,
),
>;
pub type func_inform_t = ::std::option::Option<
unsafe extern "C" fn(
arg1: *mut module_qstate,
arg2: ::std::os::raw::c_int,
arg3: *mut module_qstate,
),
>;
pub type func_clear_t = ::std::option::Option<
unsafe extern "C" fn(arg1: *mut module_qstate, arg2: ::std::os::raw::c_int),
>;
pub type func_get_mem_t = ::std::option::Option<
unsafe extern "C" fn(arg1: *mut module_env, arg2: ::std::os::raw::c_int) -> usize,
>;
pub type inplace_cb_delete_wrapped_t = ::std::option::Option<
unsafe extern "C" fn(
arg1: *mut module_env,
arg2: inplace_cb_list_type,
arg3: ::std::os::raw::c_int,
),
>;
pub type inplace_cb_register_wrapped_t = ::std::option::Option<
unsafe extern "C" fn(
arg1: *mut ::std::os::raw::c_void,
arg2: inplace_cb_list_type,
arg3: *mut ::std::os::raw::c_void,
arg4: *mut module_env,
arg5: ::std::os::raw::c_int,
) -> ::std::os::raw::c_int,
>;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct dynlibmod_env {
#[doc = " Dynamic library filename."]
pub fname: *const ::std::os::raw::c_char,
#[doc = " dynamic library handle"]
pub dynamic_library: *mut ::std::os::raw::c_void,
#[doc = " Module init function"]
pub func_init: func_init_t,
#[doc = " Module deinit function"]
pub func_deinit: func_deinit_t,
#[doc = " Module operate function"]
pub func_operate: func_operate_t,
#[doc = " Module super_inform function"]
pub func_inform: func_inform_t,
#[doc = " Module clear function"]
pub func_clear: func_clear_t,
#[doc = " Module get_mem function"]
pub func_get_mem: func_get_mem_t,
#[doc = " Wrapped inplace callback functions to circumvent callback whitelisting"]
pub inplace_cb_delete_wrapped: inplace_cb_delete_wrapped_t,
pub inplace_cb_register_wrapped: inplace_cb_register_wrapped_t,
#[doc = " Pointer to any data the dynamic library might want to keep"]
pub dyn_env: *mut ::std::os::raw::c_void,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct SignedCert {
pub magic_cert: [u8; 4usize],
pub version_major: [u8; 2usize],
@ -4964,6 +4755,222 @@ extern "C" {
nmlabs: ::std::os::raw::c_int,
) -> *mut local_data;
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct serviced_query {
_unused: [u8; 0],
}
#[doc = " The outbound list. This structure is part of the module specific query\n state."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct outbound_list {
#[doc = " The linked list of outbound query entries."]
pub first: *mut outbound_entry,
}
#[doc = " Outbound list entry. A serviced query sent by a module processing the\n query from the qstate. Double linked list to aid removal."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct outbound_entry {
#[doc = " next in list"]
pub next: *mut outbound_entry,
#[doc = " prev in list"]
pub prev: *mut outbound_entry,
#[doc = " The query that was sent out"]
pub qsent: *mut serviced_query,
#[doc = " the module query state that sent it"]
pub qstate: *mut module_qstate,
}
extern "C" {
#[doc = " Init the user allocated outbound list structure\n @param list: the list structure."]
pub fn outbound_list_init(list: *mut outbound_list);
}
extern "C" {
#[doc = " Clear the user owner outbound list structure.\n Deletes serviced queries.\n @param list: the list structure. It is cleared, but the list struct itself\n \tis callers responsibility to delete."]
pub fn outbound_list_clear(list: *mut outbound_list);
}
extern "C" {
#[doc = " Insert new entry into the list. Caller must allocate the entry with malloc.\n qstate and qsent are set by caller.\n @param list: the list to add to.\n @param e: entry to add, it is only half initialised at call start, fully\n\tinitialised at call end."]
pub fn outbound_list_insert(list: *mut outbound_list, e: *mut outbound_entry);
}
extern "C" {
#[doc = " Remove an entry from the list, and deletes it.\n Deletes serviced query in the entry.\n @param list: the list to remove from.\n @param e: the entry to remove."]
pub fn outbound_list_remove(list: *mut outbound_list, e: *mut outbound_entry);
}
extern "C" {
#[doc = " Get the module function block.\n @return: function block with function pointers to module methods."]
pub fn dynlibmod_get_funcblock() -> *mut module_func_block;
}
extern "C" {
#[doc = " dynlib module init"]
pub fn dynlibmod_init(env: *mut module_env, id: ::std::os::raw::c_int)
-> ::std::os::raw::c_int;
}
extern "C" {
#[doc = " dynlib module deinit"]
pub fn dynlibmod_deinit(env: *mut module_env, id: ::std::os::raw::c_int);
}
extern "C" {
#[doc = " dynlib module operate on a query"]
pub fn dynlibmod_operate(
qstate: *mut module_qstate,
event: module_ev,
id: ::std::os::raw::c_int,
outbound: *mut outbound_entry,
);
}
extern "C" {
#[doc = " dynlib module"]
pub fn dynlibmod_inform_super(
qstate: *mut module_qstate,
id: ::std::os::raw::c_int,
super_: *mut module_qstate,
);
}
extern "C" {
#[doc = " dynlib module cleanup query state"]
pub fn dynlibmod_clear(qstate: *mut module_qstate, id: ::std::os::raw::c_int);
}
extern "C" {
#[doc = " dynlib module alloc size routine"]
pub fn dynlibmod_get_mem(env: *mut module_env, id: ::std::os::raw::c_int) -> usize;
}
extern "C" {
pub fn dynlib_inplace_cb_reply_generic(
qinfo: *mut query_info,
qstate: *mut module_qstate,
rep: *mut reply_info,
rcode: ::std::os::raw::c_int,
edns: *mut edns_data,
opt_list_out: *mut *mut edns_option,
repinfo: *mut comm_reply,
region: *mut regional,
start_time: *mut timeval,
id: ::std::os::raw::c_int,
callback: *mut ::std::os::raw::c_void,
) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn dynlib_inplace_cb_query_generic(
qinfo: *mut query_info,
flags: u16,
qstate: *mut module_qstate,
addr: *mut sockaddr_storage,
addrlen: socklen_t,
zone: *mut u8,
zonelen: usize,
region: *mut regional,
id: ::std::os::raw::c_int,
callback: *mut ::std::os::raw::c_void,
) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn dynlib_inplace_cb_edns_back_parsed(
qstate: *mut module_qstate,
id: ::std::os::raw::c_int,
cb_args: *mut ::std::os::raw::c_void,
) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn dynlib_inplace_cb_query_response(
qstate: *mut module_qstate,
response: *mut dns_msg,
id: ::std::os::raw::c_int,
cb_args: *mut ::std::os::raw::c_void,
) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn inplace_cb_register_wrapped(
cb: *mut ::std::os::raw::c_void,
type_: inplace_cb_list_type,
cbarg: *mut ::std::os::raw::c_void,
env: *mut module_env,
id: ::std::os::raw::c_int,
) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn inplace_cb_delete_wrapped(
env: *mut module_env,
type_: inplace_cb_list_type,
id: ::std::os::raw::c_int,
);
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct cb_pair {
pub cb: *mut ::std::os::raw::c_void,
pub cb_arg: *mut ::std::os::raw::c_void,
}
#[doc = " Global state for the module."]
pub type func_init_t = ::std::option::Option<
unsafe extern "C" fn(
arg1: *mut module_env,
arg2: ::std::os::raw::c_int,
) -> ::std::os::raw::c_int,
>;
pub type func_deinit_t =
::std::option::Option<unsafe extern "C" fn(arg1: *mut module_env, arg2: ::std::os::raw::c_int)>;
pub type func_operate_t = ::std::option::Option<
unsafe extern "C" fn(
arg1: *mut module_qstate,
arg2: module_ev,
arg3: ::std::os::raw::c_int,
arg4: *mut outbound_entry,
),
>;
pub type func_inform_t = ::std::option::Option<
unsafe extern "C" fn(
arg1: *mut module_qstate,
arg2: ::std::os::raw::c_int,
arg3: *mut module_qstate,
),
>;
pub type func_clear_t = ::std::option::Option<
unsafe extern "C" fn(arg1: *mut module_qstate, arg2: ::std::os::raw::c_int),
>;
pub type func_get_mem_t = ::std::option::Option<
unsafe extern "C" fn(arg1: *mut module_env, arg2: ::std::os::raw::c_int) -> usize,
>;
pub type inplace_cb_delete_wrapped_t = ::std::option::Option<
unsafe extern "C" fn(
arg1: *mut module_env,
arg2: inplace_cb_list_type,
arg3: ::std::os::raw::c_int,
),
>;
pub type inplace_cb_register_wrapped_t = ::std::option::Option<
unsafe extern "C" fn(
arg1: *mut ::std::os::raw::c_void,
arg2: inplace_cb_list_type,
arg3: *mut ::std::os::raw::c_void,
arg4: *mut module_env,
arg5: ::std::os::raw::c_int,
) -> ::std::os::raw::c_int,
>;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct dynlibmod_env {
#[doc = " Dynamic library filename."]
pub fname: *const ::std::os::raw::c_char,
#[doc = " dynamic library handle"]
pub dynamic_library: *mut ::std::os::raw::c_void,
#[doc = " Module init function"]
pub func_init: func_init_t,
#[doc = " Module deinit function"]
pub func_deinit: func_deinit_t,
#[doc = " Module operate function"]
pub func_operate: func_operate_t,
#[doc = " Module super_inform function"]
pub func_inform: func_inform_t,
#[doc = " Module clear function"]
pub func_clear: func_clear_t,
#[doc = " Module get_mem function"]
pub func_get_mem: func_get_mem_t,
#[doc = " Wrapped inplace callback functions to circumvent callback whitelisting"]
pub inplace_cb_delete_wrapped: inplace_cb_delete_wrapped_t,
pub inplace_cb_register_wrapped: inplace_cb_register_wrapped_t,
#[doc = " Pointer to any data the dynamic library might want to keep"]
pub dyn_env: *mut ::std::os::raw::c_void,
}
#[doc = " Stack of modules."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]

10
unbound/Cargo.toml Normal file
View file

@ -0,0 +1,10 @@
[package]
name = "unbound"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
ctor = "0.2.8"
unbound-sys = { path = "../unbound-sys" }

View file

@ -1,7 +1,6 @@
use std::panic::{RefUnwindSafe, UnwindSafe};
use crate::unbound::ModuleExtState;
use crate::UnboundMod;
use crate::{module::UnboundMod, ModuleExtState};
macro_rules! impl_tuple {
($($i:tt $t:tt),*) => {

View file

@ -1,4 +1,4 @@
use crate::bindings::{module_env, module_ev, module_qstate, outbound_entry};
use crate::sys::{module_env, module_ev, module_qstate, outbound_entry};
/// Initialize module internals, like database etc.
/// Called just once on module load.
@ -16,14 +16,16 @@ pub unsafe extern "C" fn init(
env: *mut module_env,
id: ::std::os::raw::c_int,
) -> ::std::os::raw::c_int {
crate::MODULE_FACTORY.take().map_or(0, |fac| fac(env, id))
crate::module::MODULE_FACTORY
.take()
.map_or(0, |fac| fac(env, id))
}
/// Deinitialize module internals.
/// Called just once on module unload.
#[no_mangle]
pub unsafe extern "C" fn deinit(env: *mut module_env, id: ::std::os::raw::c_int) {
if let Some(module) = crate::MODULE.take() {
if let Some(module) = crate::module::MODULE.take() {
module.internal_deinit(env, id);
}
}
@ -45,7 +47,7 @@ pub unsafe extern "C" fn operate(
id: ::std::os::raw::c_int,
entry: *mut outbound_entry,
) {
if let Some(module) = crate::module() {
if let Some(module) = crate::module::module() {
module.internal_operate(qstate, event, id, entry);
}
}
@ -64,7 +66,7 @@ pub unsafe extern "C" fn inform_super(
id: ::std::os::raw::c_int,
super_qstate: *mut module_qstate,
) {
if let Some(module) = crate::module() {
if let Some(module) = crate::module::module() {
module.internal_inform_super(qstate, id, super_qstate);
}
}
@ -73,7 +75,7 @@ pub unsafe extern "C" fn inform_super(
/// back. It is used to clear up any per-query allocations.
#[no_mangle]
pub unsafe extern "C" fn clear(qstate: *mut module_qstate, id: ::std::os::raw::c_int) {
if let Some(module) = crate::module() {
if let Some(module) = crate::module::module() {
module.internal_clear(qstate, id);
}
}
@ -82,13 +84,13 @@ pub unsafe extern "C" fn clear(qstate: *mut module_qstate, id: ::std::os::raw::c
/// only happens explicitly and is only used to show memory usage to the user.
#[no_mangle]
pub unsafe extern "C" fn get_mem(env: *mut module_env, id: ::std::os::raw::c_int) -> usize {
crate::module().map_or(0, |module| module.internal_get_mem(env, id))
crate::module::module().map_or(0, |module| module.internal_get_mem(env, id))
}
// function interface assertions
const _INIT: crate::bindings::func_init_t = Some(init);
const _DEINIT: crate::bindings::func_deinit_t = Some(deinit);
const _OPERATE: crate::bindings::func_operate_t = Some(operate);
const _INFORM: crate::bindings::func_inform_t = Some(inform_super);
const _CLEAR: crate::bindings::func_clear_t = Some(clear);
const _GET_MEM: crate::bindings::func_get_mem_t = Some(get_mem);
const _INIT: crate::sys::func_init_t = Some(init);
const _DEINIT: crate::sys::func_deinit_t = Some(deinit);
const _OPERATE: crate::sys::func_operate_t = Some(operate);
const _INFORM: crate::sys::func_inform_t = Some(inform_super);
const _CLEAR: crate::sys::func_clear_t = Some(clear);
const _GET_MEM: crate::sys::func_get_mem_t = Some(get_mem);

11
unbound/src/lib.rs Normal file
View file

@ -0,0 +1,11 @@
mod combine;
mod exports;
pub mod module;
mod unbound;
pub use unbound_sys as sys;
#[doc(hidden)]
pub use ctor;
pub use unbound::*;

170
unbound/src/module.rs Normal file
View file

@ -0,0 +1,170 @@
use std::panic::{RefUnwindSafe, UnwindSafe};
use crate::{sys, ModuleExtState};
#[macro_export]
macro_rules! set_module {
($mod:ty) => {
use unbound::ctor::ctor;
#[ctor]
fn _internal_module_setup() {
unbound::module::set_unbound_mod::<$mod>();
}
};
}
pub trait UnboundMod: Send + Sync + Sized + RefUnwindSafe + UnwindSafe {
type EnvData;
type QstateData;
#[allow(clippy::result_unit_err)]
fn init(_env: &mut crate::ModuleEnvMut<Self::EnvData>) -> Result<Self, ()> {
Err(())
}
fn deinit(self, _env: &mut crate::ModuleEnvMut<Self::EnvData>) {}
fn operate(
&self,
_qstate: &mut crate::ModuleQstateMut<Self::QstateData>,
_event: crate::ModuleEvent,
_entry: Option<&mut crate::OutboundEntryMut>,
) -> Option<ModuleExtState> {
Some(ModuleExtState::Finished)
}
fn inform_super(
&self,
_qstate: &mut crate::ModuleQstateMut<Self::QstateData>,
_super_qstate: &mut crate::ModuleQstateMut<::std::ffi::c_void>,
) {
}
fn clear(&self, _qstate: &mut crate::ModuleQstateMut<Self::QstateData>) {}
fn get_mem(&self, _env: &mut crate::ModuleEnvMut<Self::EnvData>) -> usize {
0
}
}
/// # Safety
///
/// Be safe
pub(crate) unsafe trait SealedUnboundMod: Send + Sync {
unsafe fn internal_deinit(
self: Box<Self>,
env: *mut sys::module_env,
id: ::std::os::raw::c_int,
);
unsafe fn internal_operate(
&self,
qstate: *mut sys::module_qstate,
event: sys::module_ev,
id: ::std::os::raw::c_int,
entry: *mut sys::outbound_entry,
);
unsafe fn internal_inform_super(
&self,
qstate: *mut sys::module_qstate,
id: ::std::os::raw::c_int,
super_qstate: *mut sys::module_qstate,
);
unsafe fn internal_clear(&self, qstate: *mut sys::module_qstate, id: ::std::os::raw::c_int);
unsafe fn internal_get_mem(
&self,
env: *mut sys::module_env,
id: ::std::os::raw::c_int,
) -> usize;
}
unsafe impl<T: UnboundMod> SealedUnboundMod for T {
unsafe fn internal_deinit(
self: Box<Self>,
env: *mut sys::module_env,
id: ::std::os::raw::c_int,
) {
std::panic::catch_unwind(|| {
self.deinit(&mut crate::ModuleEnvMut::from_raw(env, id).unwrap());
})
.unwrap_or(());
}
unsafe fn internal_operate(
&self,
qstate: *mut sys::module_qstate,
event: sys::module_ev,
id: ::std::os::raw::c_int,
entry: *mut sys::outbound_entry,
) {
std::panic::catch_unwind(|| {
if let Some(ext_state) = self.operate(
&mut crate::ModuleQstateMut::from_raw(qstate, id).unwrap(),
event.into(),
crate::OutboundEntryMut::from_raw(entry).as_mut(),
) {
if let Some(id) = crate::check_id(id) {
(*qstate).ext_state[id] = ext_state as sys::module_ext_state;
}
}
})
.unwrap_or(());
}
unsafe fn internal_inform_super(
&self,
qstate: *mut sys::module_qstate,
id: ::std::os::raw::c_int,
super_qstate: *mut sys::module_qstate,
) {
std::panic::catch_unwind(|| {
self.inform_super(
&mut crate::ModuleQstateMut::from_raw(qstate, id).unwrap(),
&mut crate::ModuleQstateMut::from_raw(super_qstate, -1).unwrap(),
);
})
.unwrap_or(());
}
unsafe fn internal_clear(&self, qstate: *mut sys::module_qstate, id: ::std::os::raw::c_int) {
std::panic::catch_unwind(|| {
self.clear(&mut crate::ModuleQstateMut::from_raw(qstate, id).unwrap());
})
.unwrap_or(());
}
unsafe fn internal_get_mem(
&self,
env: *mut sys::module_env,
id: ::std::os::raw::c_int,
) -> usize {
std::panic::catch_unwind(|| {
self.get_mem(&mut crate::ModuleEnvMut::from_raw(env, id).unwrap())
})
.unwrap_or(0)
}
}
pub(crate) static mut MODULE: std::sync::OnceLock<Box<dyn SealedUnboundMod>> =
std::sync::OnceLock::new();
pub(crate) unsafe fn module() -> Option<&'static dyn SealedUnboundMod> {
MODULE.get().map(|x| &**x)
}
pub(crate) static mut MODULE_FACTORY: std::sync::OnceLock<
Box<
dyn Sync
+ Send
+ FnOnce(*mut sys::module_env, ::std::os::raw::c_int) -> ::std::os::raw::c_int,
>,
> = std::sync::OnceLock::new();
#[doc(hidden)]
pub fn set_unbound_mod<T: 'static + UnboundMod>() {
unsafe {
MODULE_FACTORY
.set(Box::new(|env, id| {
std::panic::catch_unwind(|| {
crate::ModuleEnvMut::from_raw(env, id)
.and_then(|mut env| T::init(&mut env).ok())
.map_or(0, |module| {
MODULE.set(Box::new(module)).map_err(|_| ()).unwrap();
1
})
})
.unwrap_or(0)
}))
.map_err(|_| "set_unbound_mod failed")
.unwrap();
}
}

View file

@ -1,5 +1,5 @@
#![allow(dead_code)]
use crate::bindings::{
use crate::sys::{
self, module_env, module_ev, module_ext_state, module_qstate, rrset_id_type, rrset_trust,
sec_status, sldns_enum_ede_code,
};
@ -13,11 +13,12 @@ use std::{
};
macro_rules! create_struct {
($ptr:tt, $name:tt, $mut:tt) => {
($ptr:tt, $name:tt, $mut:tt $(,$doc:literal)?) => {
$(#[doc = $doc])?
#[repr(transparent)]
pub struct $name<'a>(
pub(crate) *mut bindings::$ptr,
pub(crate) PhantomData<&'a bindings::$ptr>,
pub(crate) *mut sys::$ptr,
pub(crate) PhantomData<&'a sys::$ptr>,
);
#[repr(transparent)]
pub struct $mut<'a>(pub(crate) $name<'a>);
@ -27,19 +28,27 @@ macro_rules! create_struct {
&self.0
}
}
impl<'a> $name<'a> {
pub const fn as_ptr(&self) -> *const bindings::$ptr {
impl $name<'_> {
/// Returns the raw pointer to the underlying object
pub const fn as_ptr(&self) -> *const sys::$ptr {
self.0.cast_const()
}
pub unsafe fn from_raw(raw: *const bindings::$ptr) -> Option<Self> {
/// # Safety
///
/// `raw` must be either null or a valid pointer valid for the type's lifetime
pub unsafe fn from_raw(raw: *const sys::$ptr) -> Option<Self> {
(!raw.is_null()).then_some(Self(raw.cast_mut(), PhantomData))
}
}
impl<'a> $mut<'a> {
pub fn as_mut_ptr(&mut self) -> *mut bindings::$ptr {
impl $mut<'_> {
/// Returns the raw pointer to the underlying object
pub fn as_mut_ptr(&mut self) -> *mut sys::$ptr {
self.0 .0
}
pub unsafe fn from_raw(raw: *mut bindings::$ptr) -> Option<Self> {
/// # Safety
///
/// `raw` must be either null or a valid pointer valid for the type's lifetime
pub unsafe fn from_raw(raw: *mut sys::$ptr) -> Option<Self> {
(!raw.is_null()).then_some(Self($name(raw, PhantomData)))
}
}
@ -49,6 +58,7 @@ macro_rules! create_struct {
macro_rules! create_enums {
{
$(#[repr($repr:ident/$typ:ty)]
$(#[doc = $doc1:literal])?
enum $name:ident {
$($(#[doc = $doc:literal])?
$member:ident = $value:ident,)*
@ -57,17 +67,18 @@ macro_rules! create_enums {
$(
#[non_exhaustive]
#[repr($repr)]
$(#[doc = $doc1])?
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum $name {
$($(#[doc = $doc])?
$member = bindings::$value,)*
$member = sys::$value,)*
#[doc(hidden)]
Unknown = 9999,
}
impl From<$typ> for $name {
fn from(x: $typ) -> Self {
match x {
$(bindings::$value => Self::$member,)*
$(sys::$value => Self::$member,)*
_ => Self::Unknown,
}
}
@ -76,25 +87,52 @@ macro_rules! create_enums {
}
}
create_struct!(config_file, ConfigFile, ConfigFileMut);
create_struct!(
config_file,
ConfigFile,
ConfigFileMut,
" Module environment.\n Services and data provided to the module."
);
create_struct!(slabhash, SlabHash, SlabHashMut);
create_struct!(rrset_cache, RrsetCache, RrsetCacheMut);
create_struct!(infra_cache, InfraCache, InfraCacheMut);
create_struct!(
infra_cache,
InfraCache,
InfraCacheMut,
" shared infrastructure cache (edns, lameness)"
);
create_struct!(key_cache, KeyCache, KeyCacheMut);
create_struct!(outbound_entry, OutboundEntry, OutboundEntryMut);
create_struct!(query_info, QueryInfo, QueryInfoMut);
create_struct!(dns_msg, DnsMsg, DnsMsgMut);
create_struct!(reply_info, ReplyInfo, ReplyInfoMut);
create_struct!(outbound_entry, OutboundEntry, OutboundEntryMut, " Outbound list entry. A serviced query sent by a module processing the\n query from the qstate. Double linked list to aid removal.");
create_struct!(
query_info,
QueryInfo,
QueryInfoMut,
" Structure to store query information that makes answers to queries\n different."
);
create_struct!(
dns_msg,
DnsMsg,
DnsMsgMut,
" Region allocated message reply"
);
create_struct!(reply_info, ReplyInfo, ReplyInfoMut, " Structure to store DNS query and the reply packet.\n To use it, copy over the flags from reply and modify using flags from\n the query (RD,CD if not AA). prepend ID.\n\n Memory layout is:\n\to struct\n\to rrset_ref array\n\to packed_rrset_key* array.\n\n Memory layout is sometimes not packed, when the message is synthesized,\n for easy of the generation. It is allocated packed when it is copied\n from the region allocation to the malloc allocation.");
create_struct!(ub_packed_rrset_key, UbPackedRrsetKey, UbPackedRrsetKeyMut);
create_struct!(lruhash_entry, LruHashEntry, LruHashEntryMut);
create_struct!(packed_rrset_key, PackedRrsetKey, PackedRrsetKeyMut);
create_struct!(packed_rrset_data, PackedRrsetData, PackedRrsetDataMut);
create_struct!(lruhash_entry, LruHashEntry, LruHashEntryMut, " An entry into the hash table.\n To change overflow_next you need to hold the bin lock.\n To change the lru items you need to hold the hashtable lock.\n This structure is designed as part of key struct. And key pointer helps\n to get the surrounding structure. Data should be allocated on its own.");
create_struct!(
packed_rrset_key,
PackedRrsetKey,
PackedRrsetKeyMut,
" The identifying information for an RRset."
);
create_struct!(packed_rrset_data, PackedRrsetData, PackedRrsetDataMut, " RRset data.\n\n The data is packed, stored contiguously in memory.\n\n It is not always stored contiguously, in that case, an unpacked-packed\n rrset has the arrays separate. A bunch of routines work on that, but\n the packed rrset that is contiguous is for the rrset-cache and the\n cache-response routines in daemon/worker.c.\n\n memory layout:\n\to base struct\n\to rr_len size_t array\n\to rr_data uint8_t* array\n\to rr_ttl time_t array (after size_t and ptrs because those may be\n\t\t64bit and this array before those would make them unaligned).\n\t\tSince the stuff before is 32/64bit, rr_ttl is 32 bit aligned.\n\to rr_data rdata wireformats\n\to rrsig_data rdata wireformat(s)\n\n Rdata is stored in wireformat. The dname is stored in wireformat.\n TTLs are stored as absolute values (and could be expired).\n\n RRSIGs are stored in the arrays after the regular rrs.\n\n You need the packed_rrset_key to know dname, type, class of the\n resource records in this RRset. (if signed the rrsig gives the type too).\n\n On the wire an RR is:\n\tname, type, class, ttl, rdlength, rdata.\n So we need to send the following per RR:\n\tkey.dname, ttl, rr_data[i].\n\tsince key.dname ends with type and class.\n\tand rr_data starts with the rdlength.\n\tthe ttl value to send changes due to time.");
#[doc = " Module environment.\n Services and data provided to the module."]
pub struct ModuleEnv<'a, T>(
pub(crate) *mut module_env,
pub(crate) c_int,
pub(crate) PhantomData<&'a T>,
);
#[doc = " Module environment.\n Services and data provided to the module."]
pub struct ModuleEnvMut<'a, T>(pub(crate) ModuleEnv<'a, T>);
impl<'a, T> Deref for ModuleEnvMut<'a, T> {
type Target = ModuleEnv<'a, T>;
@ -102,11 +140,13 @@ impl<'a, T> Deref for ModuleEnvMut<'a, T> {
&self.0
}
}
#[doc = " Module state, per query."]
pub struct ModuleQstate<'a, T>(
pub(crate) *mut module_qstate,
pub(crate) c_int,
pub(crate) PhantomData<&'a mut T>,
);
#[doc = " Module state, per query."]
pub struct ModuleQstateMut<'a, T>(pub(crate) ModuleQstate<'a, T>);
impl<'a, T> Deref for ModuleQstateMut<'a, T> {
type Target = ModuleQstate<'a, T>;
@ -116,44 +156,68 @@ impl<'a, T> Deref for ModuleQstateMut<'a, T> {
}
impl<'a> QueryInfo<'a> {
pub fn qname(&self) -> &CStr {
unsafe { CStr::from_ptr((*self.as_ptr()).qname as *const c_char) }
#[doc = " Salient data on the query: qname, in wireformat.\n can be allocated or a pointer to outside buffer.\n User has to keep track on the status of this."]
pub fn qname(&self) -> Option<&CStr> {
if unsafe { (*self.as_ptr()).qname.is_null() } {
None
} else {
Some(unsafe { CStr::from_ptr((*self.as_ptr()).qname as *const c_char) })
}
}
#[doc = " qtype, host byte order"]
pub fn qtype(&self) -> u16 {
unsafe { (*self.as_ptr()).qtype }
}
#[doc = " qclass, host byte order"]
pub fn qclass(&self) -> u16 {
unsafe { (*self.as_ptr()).qclass }
}
}
impl<'a, T> ModuleEnv<'a, T> {
pub unsafe fn from_raw(raw: *mut bindings::module_env, id: c_int) -> Option<Self> {
/// # Safety
///
/// `raw` must be either null or a valid pointer valid for the type's lifetime.
/// `id` must either be invalid (negative), or (later) pointing to an object of type `T` in
/// some random array.
pub unsafe fn from_raw(raw: *mut sys::module_env, id: c_int) -> Option<Self> {
(!raw.is_null()).then_some(Self(raw, id, PhantomData))
}
/// Returns the raw pointer to the underlying object
pub const fn as_ptr(&self) -> *const module_env {
self.0.cast_const()
}
#[doc = " config file with config options"]
pub fn config_file(&self) -> ConfigFile<'_> {
unsafe { ConfigFile::from_raw((*self.as_ptr()).cfg).unwrap() }
}
#[doc = " shared message cache"]
pub fn msg_cache(&self) -> SlabHash<'_> {
unsafe { SlabHash::from_raw((*self.as_ptr()).msg_cache) }.unwrap()
}
#[doc = " shared rrset cache"]
pub fn rrset_cache(&self) -> RrsetCache<'_> {
unsafe { RrsetCache::from_raw((*self.as_ptr()).rrset_cache) }.unwrap()
}
#[doc = " shared infrastructure cache (edns, lameness)"]
pub fn infra_cache(&self) -> InfraCache<'_> {
unsafe { InfraCache::from_raw((*self.as_ptr()).infra_cache) }.unwrap()
}
#[doc = " shared key cache"]
pub fn key_cache(&self) -> KeyCache<'_> {
unsafe { KeyCache::from_raw((*self.as_ptr()).key_cache) }.unwrap()
}
}
impl<'a, T> ModuleEnvMut<'a, T> {
pub unsafe fn from_raw(raw: *mut bindings::module_env, id: c_int) -> Option<Self> {
/// # Safety
///
/// `raw` must be either null or a valid pointer valid for the type's lifetime
/// `id` must either be invalid (negative), or (later) pointing to an object of type `T` in
/// some random array.
pub unsafe fn from_raw(raw: *mut sys::module_env, id: c_int) -> Option<Self> {
ModuleEnv::from_raw(raw, id).map(Self)
}
/// Returns the raw pointer to the underlying object
pub fn as_mut_ptr(&mut self) -> *mut module_env {
self.0 .0
}
@ -239,6 +303,7 @@ impl<'a, T> ModuleEnvMut<'a, T> {
// )
// }
// }
#[doc = " Detach-subqueries.\n Remove all sub-query references from this query state.\n Keeps super-references of those sub-queries correct.\n Updates stat items in mesh_area structure.\n @param qstate: used to find mesh state."]
pub fn detach_subs<Y>(&mut self, qstate: &mut ModuleQstateMut<Y>) {
unsafe { (*self.as_ptr()).detach_subs.unwrap()(qstate.as_mut_ptr()) }
}
@ -283,35 +348,52 @@ impl<'a, T> ModuleEnvMut<'a, T> {
}
impl<T> ModuleQstate<'_, T> {
pub unsafe fn from_raw(raw: *mut bindings::module_qstate, id: c_int) -> Option<Self> {
/// # Safety
///
/// `raw` must be either null or a valid pointer valid for the type's lifetime
/// `id` must either be invalid (negative), or (later) pointing to an object of type `T` in
/// some random array.
pub unsafe fn from_raw(raw: *mut sys::module_qstate, id: c_int) -> Option<Self> {
(!raw.is_null()).then_some(Self(raw, id, PhantomData))
}
/// Returns the raw pointer to the underlying object
pub const fn as_ptr(&self) -> *const module_qstate {
self.0.cast_const()
}
#[doc = " which query is being answered: name, type, class"]
pub fn qinfo(&self) -> QueryInfo<'_> {
unsafe { QueryInfo::from_raw(ptr::addr_of!((*self.as_ptr()).qinfo).cast_mut()).unwrap() }
}
#[doc = " the reply message, with message for client and calling module"]
pub fn return_msg(&self) -> Option<DnsMsg<'_>> {
unsafe { DnsMsg::from_raw((*self.as_ptr()).return_msg) }
}
}
pub(crate) fn check_id(id: i32) -> Option<usize> {
(id >= 0 && id < bindings::MAX_MODULE as i32).then_some(id as usize)
(id >= 0 && id < sys::MAX_MODULE as i32).then_some(id as usize)
}
impl<T> ModuleQstateMut<'_, T> {
pub unsafe fn from_raw(raw: *mut bindings::module_qstate, id: c_int) -> Option<Self> {
/// # Safety
///
/// `raw` must be either null or a valid pointer valid for the type's lifetime
/// `id` must either be invalid (negative), or (later) pointing to an object of type `T` in
/// some random array.
pub unsafe fn from_raw(raw: *mut sys::module_qstate, id: c_int) -> Option<Self> {
ModuleQstate::from_raw(raw, id).map(Self)
}
/// Returns the raw pointer to the underlying object
pub fn as_mut_ptr(&mut self) -> *mut module_qstate {
self.0 .0
}
#[doc = " which query is being answered: name, type, class"]
pub fn qinfo_mut(&mut self) -> QueryInfoMut<'_> {
QueryInfoMut(self.qinfo())
}
#[doc = " the reply message, with message for client and calling module"]
pub fn return_msg_mut(&mut self) -> Option<DnsMsgMut<'_>> {
self.return_msg().map(DnsMsgMut)
}
#[doc = " module state"]
pub fn set_ext_state(&mut self, state: ModuleExtState) {
unsafe {
if let Some(id) = check_id(self.1) {
@ -322,48 +404,59 @@ impl<T> ModuleQstateMut<'_, T> {
}
impl DnsMsg<'_> {
#[doc = " reply info - ptr to packed repinfo structure"]
pub fn rep(&self) -> Option<ReplyInfo<'_>> {
unsafe { ReplyInfo::from_raw((*self.as_ptr()).rep) }
}
}
impl ReplyInfo<'_> {
#[doc = " the flags for the answer, host byte order."]
pub fn flags(&self) -> u16 {
unsafe { (*self.as_ptr()).flags }
}
#[doc = " This flag informs unbound the answer is authoritative and\n the AA flag should be preserved."]
pub fn authoritative(&self) -> bool {
unsafe { (*self.as_ptr()).authoritative != 0 }
}
#[doc = " Number of RRs in the query section.\n If qdcount is not 0, then it is 1, and the data that appears\n in the reply is the same as the query_info.\n Host byte order."]
pub fn qdcount(&self) -> u8 {
unsafe { (*self.as_ptr()).qdcount }
}
#[doc = " 32 bit padding to pad struct member alignment to 64 bits."]
pub fn padding(&self) -> u32 {
unsafe { (*self.as_ptr()).padding }
}
#[doc = " TTL of the entire reply (for negative caching).\n only for use when there are 0 RRsets in this message.\n if there are RRsets, check those instead."]
pub fn ttl(&self) -> Option<Duration> {
(unsafe { (*self.as_ptr()).ttl })
.try_into()
.map(Duration::from_secs)
.ok()
}
#[doc = " TTL for prefetch. After it has expired, a prefetch is suitable.\n Smaller than the TTL, otherwise the prefetch would not happen."]
pub fn prefetch_ttl(&self) -> Option<Duration> {
(unsafe { (*self.as_ptr()).prefetch_ttl })
.try_into()
.map(Duration::from_secs)
.ok()
}
#[doc = " Reply TTL extended with serve expired TTL, to limit time to serve\n expired message."]
pub fn serve_expired_ttl(&self) -> Option<Duration> {
(unsafe { (*self.as_ptr()).serve_expired_ttl })
.try_into()
.map(Duration::from_secs)
.ok()
}
#[doc = " The security status from DNSSEC validation of this message."]
pub fn security(&self) -> SecStatus {
SecStatus::from(unsafe { (*self.as_ptr()).security })
}
#[doc = " EDE (rfc8914) code with reason for DNSSEC bogus status.\n Used for caching the EDE."]
pub fn reason_bogus(&self) -> SldnsEdeCode {
SldnsEdeCode::from(unsafe { (*self.as_ptr()).reason_bogus })
}
#[doc = " EDE (rfc8914) NULL-terminated string with human-readable reason\n for DNSSEC bogus status.\n Used for caching the EDE."]
pub fn reason_bogus_str(&self) -> Option<&CStr> {
if unsafe { (*self.as_ptr()).reason_bogus_str.is_null() } {
None
@ -371,19 +464,24 @@ impl ReplyInfo<'_> {
Some(unsafe { CStr::from_ptr((*self.as_ptr()).reason_bogus_str) })
}
}
#[doc = " Number of RRsets in each section.\n The answer section. Add up the RRs in every RRset to calculate\n the number of RRs, and the count for the dns packet.\n The number of RRs in RRsets can change due to RRset updates."]
pub fn an_numrrsets(&self) -> usize {
unsafe { (*self.as_ptr()).an_numrrsets }
}
#[doc = " Count of authority section RRsets"]
pub fn ns_numrrsets(&self) -> usize {
unsafe { (*self.as_ptr()).ns_numrrsets }
}
#[doc = " Count of additional section RRsets"]
pub fn ar_numrrsets(&self) -> usize {
unsafe { (*self.as_ptr()).ar_numrrsets }
}
#[doc = " number of RRsets: an_numrrsets + ns_numrrsets + ar_numrrsets"]
pub fn rrset_count(&self) -> usize {
unsafe { (*self.as_ptr()).rrset_count }
}
pub fn rrsets(&self) -> impl '_ + Iterator<Item = UbPackedRrsetKey<'_>> {
#[doc = " List of pointers (only) to the rrsets in the order in which\n they appear in the reply message.\n Number of elements is ancount+nscount+arcount RRsets.\n This is a pointer to that array.\n Use the accessor function for access."]
pub fn rrsets(&self) -> impl '_ + DoubleEndedIterator<Item = UbPackedRrsetKey<'_>> {
let total = self.rrset_count();
let rrsets = unsafe { (*self.as_ptr()).rrsets };
(0..total).filter_map(move |i| unsafe { UbPackedRrsetKey::from_raw(*rrsets.add(i)) })
@ -391,18 +489,22 @@ impl ReplyInfo<'_> {
}
impl UbPackedRrsetKey<'_> {
#[doc = " entry into hashtable. Note the lock is never destroyed,\n even when this key is retired to the cache.\n the data pointer (if not null) points to a struct packed_rrset."]
pub fn entry(&self) -> LruHashEntry<'_> {
unsafe { LruHashEntry::from_raw(ptr::addr_of!((*self.as_ptr()).entry).cast_mut()).unwrap() }
}
#[doc = " the ID of this rrset. unique, based on threadid + sequenceno.\n ids are not reused, except after flushing the cache.\n zero is an unused entry, and never a valid id.\n Check this value after getting entry.lock.\n The other values in this struct may only be altered after changing\n the id (which needs a writelock on entry.lock)."]
pub fn id(&self) -> RrsetIdType {
unsafe { (*self.as_ptr()).id }
}
#[doc = " key data: dname, type and class"]
pub fn rk(&self) -> PackedRrsetKey<'_> {
unsafe { PackedRrsetKey::from_raw(ptr::addr_of!((*self.as_ptr()).rk).cast_mut()).unwrap() }
}
}
impl PackedRrsetKey<'_> {
#[doc = " The domain name. If not null (for id=0) it is allocated, and\n contains the wireformat domain name.\n This dname is not canonicalized."]
pub fn dname(&self) -> Option<&'_ CStr> {
if unsafe { (*self.as_ptr()).dname.is_null() } {
None
@ -410,18 +512,22 @@ impl PackedRrsetKey<'_> {
Some(unsafe { CStr::from_ptr((*self.as_ptr()).dname as *const c_char) })
}
}
#[doc = " Flags. 32bit to be easy for hashing:\n \to PACKED_RRSET_NSEC_AT_APEX\n \to PACKED_RRSET_PARENT_SIDE\n \to PACKED_RRSET_SOA_NEG\n \to PACKED_RRSET_FIXEDTTL (not supposed to be cached)\n \to PACKED_RRSET_RPZ"]
pub fn flags(&self) -> u32 {
unsafe { (*self.as_ptr()).flags }
}
#[doc = " the rrset type in network format"]
pub fn type_(&self) -> u16 {
u16::from_be(unsafe { (*self.as_ptr()).type_ })
}
#[doc = " the rrset class in network format"]
pub fn rrset_class(&self) -> u16 {
u16::from_be(unsafe { (*self.as_ptr()).rrset_class })
}
}
impl LruHashEntry<'_> {
#[doc = " data"]
pub fn data(&self) -> Option<PackedRrsetData<'_>> {
// FIXME: shouldnt pthread lock be used here?
unsafe { PackedRrsetData::from_raw((*self.as_ptr()).data.cast()) }
@ -429,31 +535,40 @@ impl LruHashEntry<'_> {
}
impl PackedRrsetData<'_> {
#[doc = " Timestamp added to TTLs in the packed data.\n Needed to support serving original TTLs."]
pub fn ttl_add(&self) -> Option<Duration> {
(unsafe { (*self.as_ptr()).ttl_add })
.try_into()
.map(Duration::from_secs)
.ok()
}
#[doc = " TTL (in seconds like time()) of the rrset.\n Same for all RRs see rfc2181(5.2)."]
pub fn ttl(&self) -> Option<Duration> {
(unsafe { (*self.as_ptr()).ttl })
.try_into()
.map(Duration::from_secs)
.ok()
}
#[doc = " number of rrs."]
pub fn count(&self) -> usize {
unsafe { (*self.as_ptr()).count }
}
#[doc = " number of rrsigs, if 0 no rrsigs"]
pub fn rrsig_count(&self) -> usize {
unsafe { (*self.as_ptr()).rrsig_count }
}
#[doc = " the trustworthiness of the rrset data"]
pub fn trust(&self) -> RrsetTrust {
RrsetTrust::from(unsafe { (*self.as_ptr()).trust })
}
#[doc = " security status of the rrset data"]
pub fn security(&self) -> SecStatus {
SecStatus::from(unsafe { (*self.as_ptr()).security })
}
pub fn rr_data(&self) -> impl '_ + Iterator<Item = (&[u8], Option<Duration>)> {
#[doc = " Every rr's rdata.\n The rr_data[i] rdata is stored in uncompressed wireformat.\n The first uint16_t of rr_data[i] is network format rdlength."]
pub fn rr_data(
&self,
) -> impl '_ + ExactSizeIterator + DoubleEndedIterator<Item = (&[u8], Option<Duration>)> {
let total = self.count();
let ttl = unsafe { (*self.as_ptr()).rr_ttl };
let len = unsafe { (*self.as_ptr()).rr_len };
@ -465,7 +580,7 @@ impl PackedRrsetData<'_> {
)
})
}
pub fn rrsig_data(&self) -> impl '_ + Iterator<Item = &[u8]> {
pub fn rrsig_data(&self) -> impl '_ + ExactSizeIterator + DoubleEndedIterator<Item = &[u8]> {
let total = self.count();
let total2 = self.rrsig_count();
let len = unsafe { (*self.as_ptr()).rr_len };
@ -479,6 +594,7 @@ type RrsetIdType = rrset_id_type;
create_enums! {
#[repr(u32/module_ev)]
#[doc = " Events that happen to modules, that start or wakeup modules."]
enum ModuleEvent {
#[doc = " new query"]
New = module_ev_module_event_new,
@ -497,6 +613,7 @@ create_enums! {
}
#[repr(u32/sec_status)]
#[doc = " Security status from validation for data.\n The order is significant; more secure, more proven later."]
enum SecStatus {
#[doc = " UNCHECKED means that object has yet to be validated."]
Unchecked = sec_status_sec_status_unchecked,
@ -543,6 +660,7 @@ create_enums! {
}
#[repr(u32/rrset_trust)]
#[doc = " RRset trustworthiness. Bigger value is more trust. RFC 2181.\n The rrset_trust_add_noAA, rrset_trust_auth_noAA, rrset_trust_add_AA,\n are mentioned as the same trustworthiness in 2181, but split up here\n for ease of processing.\n\n rrset_trust_nonauth_ans_AA, rrset_trust_ans_noAA\n are also mentioned as the same trustworthiness in 2181, but split up here\n for ease of processing.\n\n Added trust_none for a sane initial value, smaller than anything else.\n Added validated and ultimate trust for keys and rrsig validated content."]
enum RrsetTrust {
#[doc = " initial value for trust"]
None = rrset_trust_rrset_trust_none,
@ -573,6 +691,7 @@ create_enums! {
}
#[repr(u32/module_ext_state)]
#[doc = " External visible states of the module state machine\n Modules may also have an internal state.\n Modules are supposed to run to completion or until blocked."]
enum ModuleExtState {
#[doc = " initial state - new query"]
InitialState = module_ext_state_module_state_initial,
@ -606,196 +725,198 @@ impl ModuleExtState {
}
}
#[doc = " The different RR classes."]
pub mod rr_class {
use crate::bindings;
use crate::sys;
/// the Internet
pub const IN: u16 = bindings::sldns_enum_rr_class_LDNS_RR_CLASS_IN as u16;
pub const IN: u16 = sys::sldns_enum_rr_class_LDNS_RR_CLASS_IN as u16;
/// Chaos class
pub const CH: u16 = bindings::sldns_enum_rr_class_LDNS_RR_CLASS_CH as u16;
pub const CH: u16 = sys::sldns_enum_rr_class_LDNS_RR_CLASS_CH as u16;
/// Hesiod (Dyer 87)
pub const HS: u16 = bindings::sldns_enum_rr_class_LDNS_RR_CLASS_HS as u16;
pub const HS: u16 = sys::sldns_enum_rr_class_LDNS_RR_CLASS_HS as u16;
/// None class, dynamic update
pub const NONE: u16 = bindings::sldns_enum_rr_class_LDNS_RR_CLASS_NONE as u16;
pub const NONE: u16 = sys::sldns_enum_rr_class_LDNS_RR_CLASS_NONE as u16;
/// Any class
pub const ANY: u16 = bindings::sldns_enum_rr_class_LDNS_RR_CLASS_ANY as u16;
pub const ANY: u16 = sys::sldns_enum_rr_class_LDNS_RR_CLASS_ANY as u16;
}
#[doc = " The different RR types."]
pub mod rr_type {
use crate::bindings;
use crate::sys;
#[doc = " a host address"]
pub const A: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_A as u16;
pub const A: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_A as u16;
#[doc = " an authoritative name server"]
pub const NS: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_NS as u16;
pub const NS: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_NS as u16;
#[doc = " a mail destination (Obsolete - use MX)"]
pub const MD: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_MD as u16;
pub const MD: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_MD as u16;
#[doc = " a mail forwarder (Obsolete - use MX)"]
pub const MF: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_MF as u16;
pub const MF: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_MF as u16;
#[doc = " the canonical name for an alias"]
pub const CNAME: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_CNAME as u16;
pub const CNAME: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_CNAME as u16;
#[doc = " marks the start of a zone of authority"]
pub const SOA: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_SOA as u16;
pub const SOA: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_SOA as u16;
#[doc = " a mailbox domain name (EXPERIMENTAL)"]
pub const MB: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_MB as u16;
pub const MB: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_MB as u16;
#[doc = " a mail group member (EXPERIMENTAL)"]
pub const MG: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_MG as u16;
pub const MG: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_MG as u16;
#[doc = " a mail rename domain name (EXPERIMENTAL)"]
pub const MR: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_MR as u16;
pub const MR: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_MR as u16;
#[doc = " a null RR (EXPERIMENTAL)"]
pub const NULL: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_NULL as u16;
pub const NULL: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_NULL as u16;
#[doc = " a well known service description"]
pub const WKS: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_WKS as u16;
pub const WKS: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_WKS as u16;
#[doc = " a domain name pointer"]
pub const PTR: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_PTR as u16;
pub const PTR: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_PTR as u16;
#[doc = " host information"]
pub const HINFO: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_HINFO as u16;
pub const HINFO: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_HINFO as u16;
#[doc = " mailbox or mail list information"]
pub const MINFO: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_MINFO as u16;
pub const MINFO: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_MINFO as u16;
#[doc = " mail exchange"]
pub const MX: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_MX as u16;
pub const MX: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_MX as u16;
#[doc = " text strings"]
pub const TXT: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_TXT as u16;
pub const TXT: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_TXT as u16;
#[doc = " RFC1183"]
pub const RP: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_RP as u16;
pub const RP: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_RP as u16;
#[doc = " RFC1183"]
pub const AFSDB: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_AFSDB as u16;
pub const AFSDB: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_AFSDB as u16;
#[doc = " RFC1183"]
pub const X25: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_X25 as u16;
pub const X25: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_X25 as u16;
#[doc = " RFC1183"]
pub const ISDN: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_ISDN as u16;
pub const ISDN: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_ISDN as u16;
#[doc = " RFC1183"]
pub const RT: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_RT as u16;
pub const RT: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_RT as u16;
#[doc = " RFC1706"]
pub const NSAP: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_NSAP as u16;
pub const NSAP: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_NSAP as u16;
#[doc = " RFC1348"]
pub const NSAP_PTR: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_NSAP_PTR as u16;
pub const NSAP_PTR: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_NSAP_PTR as u16;
#[doc = " 2535typecode"]
pub const SIG: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_SIG as u16;
pub const SIG: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_SIG as u16;
#[doc = " 2535typecode"]
pub const KEY: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_KEY as u16;
pub const KEY: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_KEY as u16;
#[doc = " RFC2163"]
pub const PX: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_PX as u16;
pub const PX: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_PX as u16;
#[doc = " RFC1712"]
pub const GPOS: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_GPOS as u16;
pub const GPOS: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_GPOS as u16;
#[doc = " ipv6 address"]
pub const AAAA: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_AAAA as u16;
pub const AAAA: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_AAAA as u16;
#[doc = " LOC record RFC1876"]
pub const LOC: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_LOC as u16;
pub const LOC: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_LOC as u16;
#[doc = " 2535typecode"]
pub const NXT: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_NXT as u16;
pub const NXT: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_NXT as u16;
#[doc = " draft-ietf-nimrod-dns-01.txt"]
pub const EID: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_EID as u16;
pub const EID: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_EID as u16;
#[doc = " draft-ietf-nimrod-dns-01.txt"]
pub const NIMLOC: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_NIMLOC as u16;
pub const NIMLOC: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_NIMLOC as u16;
#[doc = " SRV record RFC2782"]
pub const SRV: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_SRV as u16;
pub const SRV: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_SRV as u16;
#[doc = " http://www.jhsoft.com/rfc/af-saa-0069.000.rtf"]
pub const ATMA: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_ATMA as u16;
pub const ATMA: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_ATMA as u16;
#[doc = " RFC2915"]
pub const NAPTR: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_NAPTR as u16;
pub const NAPTR: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_NAPTR as u16;
#[doc = " RFC2230"]
pub const KX: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_KX as u16;
pub const KX: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_KX as u16;
#[doc = " RFC2538"]
pub const CERT: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_CERT as u16;
pub const CERT: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_CERT as u16;
#[doc = " RFC2874"]
pub const A6: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_A6 as u16;
pub const A6: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_A6 as u16;
#[doc = " RFC2672"]
pub const DNAME: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_DNAME as u16;
pub const DNAME: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_DNAME as u16;
#[doc = " dnsind-kitchen-sink-02.txt"]
pub const SINK: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_SINK as u16;
pub const SINK: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_SINK as u16;
#[doc = " Pseudo OPT record..."]
pub const OPT: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_OPT as u16;
pub const OPT: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_OPT as u16;
#[doc = " RFC3123"]
pub const APL: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_APL as u16;
pub const APL: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_APL as u16;
#[doc = " RFC4034, RFC3658"]
pub const DS: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_DS as u16;
pub const DS: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_DS as u16;
#[doc = " SSH Key Fingerprint"]
pub const SSHFP: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_SSHFP as u16;
pub const SSHFP: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_SSHFP as u16;
#[doc = " IPsec Key"]
pub const IPSECKEY: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_IPSECKEY as u16;
pub const IPSECKEY: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_IPSECKEY as u16;
#[doc = " DNSSEC"]
pub const RRSIG: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_RRSIG as u16;
pub const RRSIG: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_RRSIG as u16;
#[doc = " DNSSEC"]
pub const NSEC: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_NSEC as u16;
pub const NSEC: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_NSEC as u16;
#[doc = " DNSSEC"]
pub const DNSKEY: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_DNSKEY as u16;
pub const DNSKEY: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_DNSKEY as u16;
#[doc = " DNSSEC"]
pub const DHCID: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_DHCID as u16;
pub const DHCID: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_DHCID as u16;
#[doc = " DNSSEC"]
pub const NSEC3: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_NSEC3 as u16;
pub const NSEC3: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_NSEC3 as u16;
#[doc = " DNSSEC"]
pub const NSEC3PARAM: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_NSEC3PARAM as u16;
pub const NSEC3PARAM: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_NSEC3PARAM as u16;
#[doc = " DNSSEC"]
pub const NSEC3PARAMS: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_NSEC3PARAMS as u16;
pub const NSEC3PARAMS: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_NSEC3PARAMS as u16;
#[doc = " DNSSEC"]
pub const TLSA: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_TLSA as u16;
pub const TLSA: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_TLSA as u16;
#[doc = " DNSSEC"]
pub const SMIMEA: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_SMIMEA as u16;
pub const SMIMEA: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_SMIMEA as u16;
#[doc = " DNSSEC"]
pub const HIP: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_HIP as u16;
pub const HIP: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_HIP as u16;
#[doc = " draft-reid-dnsext-zs"]
pub const NINFO: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_NINFO as u16;
pub const NINFO: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_NINFO as u16;
#[doc = " draft-reid-dnsext-rkey"]
pub const RKEY: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_RKEY as u16;
pub const RKEY: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_RKEY as u16;
#[doc = " draft-ietf-dnsop-trust-history"]
pub const TALINK: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_TALINK as u16;
pub const TALINK: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_TALINK as u16;
#[doc = " draft-ietf-dnsop-trust-history"]
pub const CDS: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_CDS as u16;
pub const CDS: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_CDS as u16;
#[doc = " RFC 7344"]
pub const CDNSKEY: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_CDNSKEY as u16;
pub const CDNSKEY: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_CDNSKEY as u16;
#[doc = " RFC 7344"]
pub const OPENPGPKEY: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_OPENPGPKEY as u16;
pub const OPENPGPKEY: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_OPENPGPKEY as u16;
#[doc = " RFC 7344"]
pub const CSYNC: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_CSYNC as u16;
pub const CSYNC: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_CSYNC as u16;
#[doc = " RFC 7344"]
pub const ZONEMD: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_ZONEMD as u16;
pub const ZONEMD: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_ZONEMD as u16;
#[doc = " RFC 7344"]
pub const SVCB: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_SVCB as u16;
pub const SVCB: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_SVCB as u16;
#[doc = " RFC 7344"]
pub const HTTPS: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_HTTPS as u16;
pub const HTTPS: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_HTTPS as u16;
#[doc = " RFC 7344"]
pub const SPF: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_SPF as u16;
pub const SPF: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_SPF as u16;
#[doc = " RFC 7344"]
pub const UINFO: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_UINFO as u16;
pub const UINFO: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_UINFO as u16;
#[doc = " RFC 7344"]
pub const UID: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_UID as u16;
pub const UID: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_UID as u16;
#[doc = " RFC 7344"]
pub const GID: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_GID as u16;
pub const GID: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_GID as u16;
#[doc = " RFC 7344"]
pub const UNSPEC: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_UNSPEC as u16;
pub const UNSPEC: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_UNSPEC as u16;
#[doc = " RFC 7344"]
pub const NID: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_NID as u16;
pub const NID: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_NID as u16;
#[doc = " RFC 7344"]
pub const L32: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_L32 as u16;
pub const L32: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_L32 as u16;
#[doc = " RFC 7344"]
pub const L64: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_L64 as u16;
pub const L64: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_L64 as u16;
#[doc = " RFC 7344"]
pub const LP: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_LP as u16;
pub const LP: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_LP as u16;
#[doc = " draft-jabley-dnsext-eui48-eui64-rrtypes"]
pub const EUI48: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_EUI48 as u16;
pub const EUI48: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_EUI48 as u16;
#[doc = " draft-jabley-dnsext-eui48-eui64-rrtypes"]
pub const EUI64: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_EUI64 as u16;
pub const EUI64: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_EUI64 as u16;
#[doc = " draft-jabley-dnsext-eui48-eui64-rrtypes"]
pub const TKEY: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_TKEY as u16;
pub const TKEY: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_TKEY as u16;
#[doc = " draft-jabley-dnsext-eui48-eui64-rrtypes"]
pub const TSIG: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_TSIG as u16;
pub const TSIG: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_TSIG as u16;
#[doc = " draft-jabley-dnsext-eui48-eui64-rrtypes"]
pub const IXFR: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_IXFR as u16;
pub const IXFR: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_IXFR as u16;
#[doc = " draft-jabley-dnsext-eui48-eui64-rrtypes"]
pub const AXFR: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_AXFR as u16;
pub const AXFR: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_AXFR as u16;
#[doc = " A request for mailbox-related records (MB, MG or MR)"]
pub const MAILB: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_MAILB as u16;
pub const MAILB: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_MAILB as u16;
#[doc = " A request for mail agent RRs (Obsolete - see MX)"]
pub const MAILA: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_MAILA as u16;
pub const MAILA: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_MAILA as u16;
#[doc = " any type (wildcard)"]
pub const ANY: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_ANY as u16;
pub const ANY: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_ANY as u16;
#[doc = " any type (wildcard)"]
pub const URI: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_URI as u16;
pub const URI: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_URI as u16;
#[doc = " any type (wildcard)"]
pub const CAA: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_CAA as u16;
pub const CAA: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_CAA as u16;
#[doc = " any type (wildcard)"]
pub const AVC: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_AVC as u16;
pub const AVC: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_AVC as u16;
#[doc = " DNSSEC Trust Authorities"]
pub const TA: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_TA as u16;
pub const TA: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_TA as u16;
#[doc = " DNSSEC Trust Authorities"]
pub const DLV: u16 = bindings::sldns_enum_rr_type_LDNS_RR_TYPE_DLV as u16;
pub const DLV: u16 = sys::sldns_enum_rr_type_LDNS_RR_TYPE_DLV as u16;
}