Refactor code to reduce duplication among gethostbyname(3|4)_r
This commit is contained in:
parent
516bf4000c
commit
8082509da0
|
@ -8,6 +8,12 @@ edition = "2021"
|
||||||
authors = ["Matteo Settenvini <matteo.settenvini@montecristosoftware.eu"]
|
authors = ["Matteo Settenvini <matteo.settenvini@montecristosoftware.eu"]
|
||||||
license = "GPL-3.0-or-later"
|
license = "GPL-3.0-or-later"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
strip = true
|
||||||
|
lto = true
|
||||||
|
codegen-units = 1
|
||||||
|
panic = "abort"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["cdylib"]
|
crate-type = ["cdylib"]
|
||||||
name = "nss_malcontent"
|
name = "nss_malcontent"
|
||||||
|
@ -31,4 +37,5 @@ log = "0.4"
|
||||||
nix = { version = "0.25", features = ["socket", "user", "sched"] }
|
nix = { version = "0.25", features = ["socket", "user", "sched"] }
|
||||||
tokio = { version = "1", features = ["rt"] }
|
tokio = { version = "1", features = ["rt"] }
|
||||||
trust-dns-resolver = "0.21"
|
trust-dns-resolver = "0.21"
|
||||||
|
trust-dns-proto = "0.21"
|
||||||
zbus = { version = "3.0", default-features = false, features = ["tokio"] }
|
zbus = { version = "3.0", default-features = false, features = ["tokio"] }
|
||||||
|
|
|
@ -2,38 +2,57 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::helpers::{ips_to_gaih_addr, set_if_valid},
|
crate::helpers::{records_to_gaih_addr, records_to_hostent, set_if_valid},
|
||||||
crate::nss_bindings::{gaih_addrtuple, nss_status, HErrno},
|
crate::nss_bindings::{gaih_addrtuple, nss_status, HErrno},
|
||||||
crate::policy_checker::{PolicyChecker as _, POLICY_CHECKER},
|
crate::policy_checker::{PolicyChecker as _, POLICY_CHECKER},
|
||||||
libc::{hostent, size_t},
|
libc::{c_char, c_int, hostent, size_t},
|
||||||
|
nix::errno,
|
||||||
nix::errno::Errno,
|
nix::errno::Errno,
|
||||||
std::ffi::CStr,
|
std::ffi::CStr,
|
||||||
std::os::raw::{c_char, c_int},
|
trust_dns_proto::rr::record_type::RecordType,
|
||||||
|
trust_dns_proto::xfer::dns_request::DnsRequestOptions,
|
||||||
|
trust_dns_resolver::{lookup::Lookup, lookup_ip::LookupIp},
|
||||||
};
|
};
|
||||||
|
|
||||||
// See https://support.mozilla.org/en-US/kb/configuring-networks-disable-dns-over-https
|
// See https://support.mozilla.org/en-US/kb/configuring-networks-disable-dns-over-https
|
||||||
const CANARY_HOSTNAME: &str = "use-application-dns.net";
|
const CANARY_HOSTNAME: &str = "use-application-dns.net";
|
||||||
|
|
||||||
pub async unsafe fn gethostbyname4_r(
|
pub struct Args {
|
||||||
name: *const c_char,
|
pub name: *const c_char,
|
||||||
pat: *mut *mut gaih_addrtuple,
|
pub family: c_int,
|
||||||
buffer: *mut c_char,
|
pub buffer: *mut c_char,
|
||||||
buflen: size_t,
|
pub buflen: size_t,
|
||||||
errnop: *mut Errno,
|
pub errnop: *mut Errno,
|
||||||
h_errnop: *mut HErrno,
|
pub h_errnop: *mut HErrno,
|
||||||
ttlp: *mut i32,
|
pub ttlp: *mut i32,
|
||||||
) -> nss_status {
|
pub result: Result,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Result {
|
||||||
|
V3(HostEnt),
|
||||||
|
V4(*mut *mut gaih_addrtuple),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct HostEnt {
|
||||||
|
pub host: *mut hostent,
|
||||||
|
pub canonp: *mut *mut char,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async unsafe fn with(args: &mut Args) -> nss_status {
|
||||||
|
set_if_valid(args.errnop, errno::from_i32(0));
|
||||||
|
set_if_valid(args.h_errnop, HErrno::Success);
|
||||||
|
|
||||||
match POLICY_CHECKER.resolver(None) {
|
match POLICY_CHECKER.resolver(None) {
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
// no restrictions for user, the next NSS module will decide
|
// no restrictions for user, the next NSS module will decide
|
||||||
nss_status::NSS_STATUS_NOTFOUND
|
nss_status::NSS_STATUS_NOTFOUND
|
||||||
}
|
}
|
||||||
Ok(Some(resolver)) => {
|
Ok(Some(resolver)) => {
|
||||||
let name = match CStr::from_ptr(name).to_str() {
|
let name = match CStr::from_ptr(args.name).to_str() {
|
||||||
Ok(name) => name,
|
Ok(name) => name,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
set_if_valid(errnop, Errno::EINVAL);
|
set_if_valid(args.errnop, Errno::EINVAL);
|
||||||
set_if_valid(h_errnop, HErrno::Internal);
|
set_if_valid(args.h_errnop, HErrno::Internal);
|
||||||
return nss_status::NSS_STATUS_TRYAGAIN;
|
return nss_status::NSS_STATUS_TRYAGAIN;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -41,54 +60,27 @@ pub async unsafe fn gethostbyname4_r(
|
||||||
// disable application-based DNS for those applications
|
// disable application-based DNS for those applications
|
||||||
// (notably, Firefox) that support it
|
// (notably, Firefox) that support it
|
||||||
if name == CANARY_HOSTNAME {
|
if name == CANARY_HOSTNAME {
|
||||||
set_if_valid(h_errnop, HErrno::HostNotFound);
|
set_if_valid(args.h_errnop, HErrno::HostNotFound);
|
||||||
return nss_status::NSS_STATUS_SUCCESS;
|
return nss_status::NSS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
match resolver.lookup_ip(name).await {
|
let lookup: std::result::Result<Lookup, _> = match args.family {
|
||||||
Ok(result) if result.iter().peekable().peek().is_none() => {
|
libc::AF_UNSPEC => resolver.lookup_ip(name).await.map(LookupIp::into),
|
||||||
set_if_valid(h_errnop, HErrno::HostNotFound);
|
libc::AF_INET => {
|
||||||
nss_status::NSS_STATUS_SUCCESS
|
resolver
|
||||||
|
.lookup(name, RecordType::A, DnsRequestOptions::default())
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
Ok(result) => {
|
libc::AF_INET6 => {
|
||||||
if pat == std::ptr::null_mut() {
|
resolver
|
||||||
set_if_valid(errnop, Errno::EINVAL);
|
.lookup(name, RecordType::AAAA, DnsRequestOptions::default())
|
||||||
set_if_valid(h_errnop, HErrno::Internal);
|
.await
|
||||||
return nss_status::NSS_STATUS_TRYAGAIN;
|
|
||||||
}
|
}
|
||||||
|
_ => return nss_status::NSS_STATUS_NOTFOUND,
|
||||||
|
};
|
||||||
|
|
||||||
let ttl = result
|
match lookup {
|
||||||
.valid_until()
|
Ok(result) => prepare_response(args, result),
|
||||||
.duration_since(std::time::Instant::now())
|
|
||||||
.as_secs();
|
|
||||||
set_if_valid(
|
|
||||||
ttlp,
|
|
||||||
if ttl < (i32::MAX as u64) {
|
|
||||||
ttl as i32
|
|
||||||
} else {
|
|
||||||
i32::MAX
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
let buf = std::slice::from_raw_parts_mut(buffer as *mut u8, buflen);
|
|
||||||
match ips_to_gaih_addr(result, buf) {
|
|
||||||
Ok(addrs) => {
|
|
||||||
// DEBUG: eprintln!("{:?} => {:?}", addrs, *addrs);
|
|
||||||
*pat = addrs;
|
|
||||||
nss_status::NSS_STATUS_SUCCESS
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
set_if_valid(
|
|
||||||
errnop,
|
|
||||||
err.raw_os_error()
|
|
||||||
.map(Errno::from_i32)
|
|
||||||
.unwrap_or(Errno::EAGAIN),
|
|
||||||
);
|
|
||||||
set_if_valid(h_errnop, HErrno::Internal);
|
|
||||||
nss_status::NSS_STATUS_TRYAGAIN
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::warn!("{}", err);
|
log::warn!("{}", err);
|
||||||
nss_status::NSS_STATUS_UNAVAIL
|
nss_status::NSS_STATUS_UNAVAIL
|
||||||
|
@ -102,16 +94,77 @@ pub async unsafe fn gethostbyname4_r(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async unsafe fn gethostbyname3_r(
|
unsafe fn prepare_response(
|
||||||
_name: *const c_char,
|
args: &mut Args,
|
||||||
_af: c_int,
|
lookup: trust_dns_resolver::lookup::Lookup,
|
||||||
_host: *mut hostent,
|
|
||||||
_buffer: *mut c_char,
|
|
||||||
_buflen: size_t,
|
|
||||||
_errnop: *mut Errno,
|
|
||||||
_h_errnop: *mut HErrno,
|
|
||||||
_ttlp: *mut i32,
|
|
||||||
_canonp: *mut *mut char,
|
|
||||||
) -> nss_status {
|
) -> nss_status {
|
||||||
todo!()
|
if lookup.iter().peekable().peek().is_none() {
|
||||||
|
set_if_valid(args.h_errnop, HErrno::HostNotFound);
|
||||||
|
return nss_status::NSS_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ttl = lookup
|
||||||
|
.valid_until()
|
||||||
|
.duration_since(std::time::Instant::now())
|
||||||
|
.as_secs();
|
||||||
|
set_if_valid(
|
||||||
|
args.ttlp,
|
||||||
|
if ttl < (i32::MAX as u64) {
|
||||||
|
ttl as i32
|
||||||
|
} else {
|
||||||
|
i32::MAX
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let buf = std::slice::from_raw_parts_mut(args.buffer as *mut u8, args.buflen);
|
||||||
|
let ret = match &mut args.result {
|
||||||
|
Result::V3(hostent) => {
|
||||||
|
if hostent.host.is_null() {
|
||||||
|
set_if_valid(args.errnop, Errno::EINVAL);
|
||||||
|
set_if_valid(args.h_errnop, HErrno::Internal);
|
||||||
|
return nss_status::NSS_STATUS_TRYAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
match records_to_hostent(lookup.into(), hostent, buf) {
|
||||||
|
Ok(_) => nss_status::NSS_STATUS_SUCCESS,
|
||||||
|
Err(err) => {
|
||||||
|
set_if_valid(
|
||||||
|
args.errnop,
|
||||||
|
err.raw_os_error()
|
||||||
|
.map(Errno::from_i32)
|
||||||
|
.unwrap_or(Errno::EAGAIN),
|
||||||
|
);
|
||||||
|
set_if_valid(args.h_errnop, HErrno::Internal);
|
||||||
|
nss_status::NSS_STATUS_TRYAGAIN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Result::V4(pat) => {
|
||||||
|
if pat.is_null() {
|
||||||
|
set_if_valid(args.errnop, Errno::EINVAL);
|
||||||
|
set_if_valid(args.h_errnop, HErrno::Internal);
|
||||||
|
return nss_status::NSS_STATUS_TRYAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
match records_to_gaih_addr(lookup.into(), buf) {
|
||||||
|
Ok(addrs) => {
|
||||||
|
// DEBUG: eprintln!("{:?} => {:?}", addrs, *addrs);
|
||||||
|
**pat = addrs;
|
||||||
|
nss_status::NSS_STATUS_SUCCESS
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
set_if_valid(
|
||||||
|
args.errnop,
|
||||||
|
err.raw_os_error()
|
||||||
|
.map(Errno::from_i32)
|
||||||
|
.unwrap_or(Errno::EAGAIN),
|
||||||
|
);
|
||||||
|
set_if_valid(args.h_errnop, HErrno::Internal);
|
||||||
|
nss_status::NSS_STATUS_TRYAGAIN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ret
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
use {
|
use {
|
||||||
|
crate::gethostbyname::HostEnt,
|
||||||
crate::nss_bindings::gaih_addrtuple,
|
crate::nss_bindings::gaih_addrtuple,
|
||||||
anyhow::{bail, Result},
|
anyhow::{bail, Result},
|
||||||
libc::{AF_INET, AF_INET6},
|
libc::{AF_INET, AF_INET6},
|
||||||
|
@ -9,31 +10,35 @@ use {
|
||||||
once_cell::sync::Lazy,
|
once_cell::sync::Lazy,
|
||||||
std::ffi::CString,
|
std::ffi::CString,
|
||||||
std::mem::{align_of, size_of},
|
std::mem::{align_of, size_of},
|
||||||
std::net::IpAddr,
|
trust_dns_proto::rr::RData,
|
||||||
trust_dns_resolver::lookup_ip::LookupIp,
|
trust_dns_resolver::lookup::Lookup,
|
||||||
};
|
};
|
||||||
|
|
||||||
static RUNTIME: Lazy<std::io::Result<tokio::runtime::Handle>> = Lazy::new(|| {
|
static RUNTIME: Lazy<std::io::Result<tokio::runtime::Runtime>> = Lazy::new(|| {
|
||||||
// The runtime should remain single-threaded, some
|
// The runtime should remain single-threaded, some
|
||||||
// programs depend on it (e.g. programs calling unshare())
|
// programs depend on it (e.g. programs calling unshare())
|
||||||
let rt = tokio::runtime::Builder::new_current_thread().build()?;
|
let rt = tokio::runtime::Builder::new_current_thread()
|
||||||
Ok(rt.handle().clone())
|
.enable_time()
|
||||||
|
.enable_io()
|
||||||
|
.build()?;
|
||||||
|
Ok(rt)
|
||||||
});
|
});
|
||||||
|
|
||||||
pub unsafe fn ips_to_gaih_addr(
|
// TODO: error handling codes chosen a bit sloppily
|
||||||
ips: LookupIp,
|
pub unsafe fn records_to_gaih_addr(
|
||||||
|
lookup: Lookup,
|
||||||
mut buf: &mut [u8],
|
mut buf: &mut [u8],
|
||||||
) -> std::io::Result<*mut gaih_addrtuple> {
|
) -> std::io::Result<*mut gaih_addrtuple> {
|
||||||
const GAIH_ADDRTUPLE_SZ: usize = size_of::<gaih_addrtuple>();
|
const GAIH_ADDRTUPLE_SZ: usize = size_of::<gaih_addrtuple>();
|
||||||
|
|
||||||
let mut ret = std::ptr::null_mut();
|
let mut ret = std::ptr::null_mut();
|
||||||
let query = ips.query();
|
|
||||||
|
|
||||||
let name = CString::new(query.name().to_utf8()).unwrap(); // TODO: .map_err() and fail more graciously
|
|
||||||
let mut prev_link: *mut *mut gaih_addrtuple = std::ptr::null_mut();
|
let mut prev_link: *mut *mut gaih_addrtuple = std::ptr::null_mut();
|
||||||
|
|
||||||
for addr in ips {
|
for record in lookup.record_iter() {
|
||||||
// First add the name to the buffer
|
// First add the name to the buffer
|
||||||
|
let name = CString::new(record.name().to_utf8())
|
||||||
|
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e.to_string()))?;
|
||||||
|
|
||||||
let offset = buf.as_ptr().align_offset(align_of::<libc::c_char>());
|
let offset = buf.as_ptr().align_offset(align_of::<libc::c_char>());
|
||||||
let name_src = name.as_bytes_with_nul();
|
let name_src = name.as_bytes_with_nul();
|
||||||
let name_dest = buf.as_mut_ptr().add(offset);
|
let name_dest = buf.as_mut_ptr().add(offset);
|
||||||
|
@ -60,15 +65,17 @@ pub unsafe fn ips_to_gaih_addr(
|
||||||
set_if_valid(prev_link, &mut *tuple); // link from previous tuple to this tuple
|
set_if_valid(prev_link, &mut *tuple); // link from previous tuple to this tuple
|
||||||
prev_link = &mut (*tuple).next;
|
prev_link = &mut (*tuple).next;
|
||||||
|
|
||||||
match addr {
|
match record.data() {
|
||||||
IpAddr::V4(addr) => {
|
Some(RData::A(addr)) => {
|
||||||
tuple.family = AF_INET;
|
tuple.family = AF_INET;
|
||||||
tuple.addr[0] = std::mem::transmute_copy(&addr.octets());
|
tuple.addr[0] = std::mem::transmute_copy(&addr.octets());
|
||||||
}
|
}
|
||||||
IpAddr::V6(addr) => {
|
Some(RData::AAAA(addr)) => {
|
||||||
tuple.family = AF_INET6;
|
tuple.family = AF_INET6;
|
||||||
tuple.addr = std::mem::transmute_copy(&addr.octets());
|
tuple.addr = std::mem::transmute_copy(&addr.octets());
|
||||||
}
|
}
|
||||||
|
Some(_) => return Err(Errno::EBADMSG.into()),
|
||||||
|
None => return Err(Errno::ENODATA.into()),
|
||||||
}
|
}
|
||||||
|
|
||||||
if ret == std::ptr::null_mut() {
|
if ret == std::ptr::null_mut() {
|
||||||
|
@ -81,6 +88,37 @@ pub unsafe fn ips_to_gaih_addr(
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub unsafe fn records_to_hostent(
|
||||||
|
lookup: Lookup,
|
||||||
|
_hostent: &mut HostEnt,
|
||||||
|
mut _buf: &mut [u8],
|
||||||
|
) -> std::io::Result<()> {
|
||||||
|
|
||||||
|
// char *h_name Official name of the host.
|
||||||
|
// char **h_aliases A pointer to an array of pointers to
|
||||||
|
// alternative host names, terminated by a
|
||||||
|
// null pointer.
|
||||||
|
// int h_addrtype Address type.
|
||||||
|
// int h_length The length, in bytes, of the address.
|
||||||
|
// char **h_addr_list A pointer to an array of pointers to network
|
||||||
|
// addresses (in network byte order) for the host,
|
||||||
|
// terminated by a null pointer.
|
||||||
|
|
||||||
|
// In C struct hostent:
|
||||||
|
//
|
||||||
|
// - for the type of queries we perform, we can assume h_aliases
|
||||||
|
// is an empty array.
|
||||||
|
// - hostent is limited to just one address type for all addresses
|
||||||
|
// in the list. We pick the type of first result, and only
|
||||||
|
// append addresses of the same type.
|
||||||
|
|
||||||
|
for record in lookup.record_iter() {
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_if_valid<T>(ptr: *mut T, val: T) {
|
pub fn set_if_valid<T>(ptr: *mut T, val: T) {
|
||||||
if !ptr.is_null() {
|
if !ptr.is_null() {
|
||||||
unsafe { *ptr = val };
|
unsafe { *ptr = val };
|
||||||
|
@ -93,7 +131,7 @@ where
|
||||||
{
|
{
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
match RUNTIME.deref() {
|
match RUNTIME.deref() {
|
||||||
Ok(rt_handle) => Ok(rt_handle.block_on(async { f.await })),
|
Ok(rt) => Ok(rt.block_on(async { f.await })),
|
||||||
Err(e) => bail!("Unable to start tokio runtime: {}", e),
|
Err(e) => bail!("Unable to start tokio runtime: {}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,10 @@
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::gethostbyaddr::gethostbyaddr2_r,
|
crate::gethostbyaddr::gethostbyaddr2_r,
|
||||||
crate::gethostbyname::{gethostbyname3_r, gethostbyname4_r},
|
crate::gethostbyname,
|
||||||
crate::helpers::{block_on, set_if_valid},
|
crate::helpers::{block_on, set_if_valid},
|
||||||
crate::nss_bindings::{gaih_addrtuple, nss_status, HErrno},
|
crate::nss_bindings::{gaih_addrtuple, nss_status, HErrno},
|
||||||
libc::{hostent, size_t, socklen_t, AF_INET},
|
libc::{hostent, size_t, socklen_t, AF_INET},
|
||||||
nix::errno,
|
|
||||||
nix::errno::Errno,
|
nix::errno::Errno,
|
||||||
std::os::raw::{c_char, c_int, c_void},
|
std::os::raw::{c_char, c_int, c_void},
|
||||||
std::ptr,
|
std::ptr,
|
||||||
|
@ -25,16 +24,22 @@ pub unsafe extern "C" fn _nss_malcontent_gethostbyname4_r(
|
||||||
h_errnop: *mut HErrno,
|
h_errnop: *mut HErrno,
|
||||||
ttlp: *mut i32,
|
ttlp: *mut i32,
|
||||||
) -> nss_status {
|
) -> nss_status {
|
||||||
set_if_valid(errnop, errno::from_i32(0));
|
let mut args = gethostbyname::Args {
|
||||||
set_if_valid(h_errnop, HErrno::Success);
|
name,
|
||||||
|
family: 0,
|
||||||
|
result: gethostbyname::Result::V4(pat),
|
||||||
|
buffer,
|
||||||
|
buflen,
|
||||||
|
errnop,
|
||||||
|
h_errnop,
|
||||||
|
ttlp,
|
||||||
|
};
|
||||||
|
|
||||||
match block_on(async {
|
match block_on(async { gethostbyname::with(&mut args).await }) {
|
||||||
gethostbyname4_r(name, pat, buffer, buflen, errnop, h_errnop, ttlp).await
|
|
||||||
}) {
|
|
||||||
Ok(status) => status,
|
Ok(status) => status,
|
||||||
Err(runtime_error) => {
|
Err(runtime_error) => {
|
||||||
log::error!("gethostbyname4_r: {}", runtime_error);
|
log::error!("gethostbyname4_r: {}", runtime_error);
|
||||||
set_if_valid(h_errnop, HErrno::Internal);
|
set_if_valid(args.h_errnop, HErrno::Internal);
|
||||||
nss_status::NSS_STATUS_TRYAGAIN
|
nss_status::NSS_STATUS_TRYAGAIN
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,15 +57,20 @@ pub unsafe extern "C" fn _nss_malcontent_gethostbyname3_r(
|
||||||
ttlp: *mut i32,
|
ttlp: *mut i32,
|
||||||
canonp: *mut *mut char,
|
canonp: *mut *mut char,
|
||||||
) -> nss_status {
|
) -> nss_status {
|
||||||
set_if_valid(errnop, errno::from_i32(0));
|
let result = gethostbyname::HostEnt { host, canonp };
|
||||||
set_if_valid(h_errnop, HErrno::Success);
|
|
||||||
|
|
||||||
match block_on(async {
|
let mut args = gethostbyname::Args {
|
||||||
gethostbyname3_r(
|
name,
|
||||||
name, af, host, buffer, buflen, errnop, h_errnop, ttlp, canonp,
|
family: af,
|
||||||
)
|
result: gethostbyname::Result::V3(result),
|
||||||
.await
|
buffer,
|
||||||
}) {
|
buflen,
|
||||||
|
errnop,
|
||||||
|
h_errnop,
|
||||||
|
ttlp,
|
||||||
|
};
|
||||||
|
|
||||||
|
match block_on(async { gethostbyname::with(&mut args).await }) {
|
||||||
Ok(status) => status,
|
Ok(status) => status,
|
||||||
Err(runtime_error) => {
|
Err(runtime_error) => {
|
||||||
log::error!("gethostbyname3_r: {}", runtime_error);
|
log::error!("gethostbyname3_r: {}", runtime_error);
|
||||||
|
@ -129,7 +139,7 @@ pub unsafe extern "C" fn _nss_malcontent_gethostbyaddr2_r(
|
||||||
h_errnop: *mut HErrno,
|
h_errnop: *mut HErrno,
|
||||||
ttlp: *mut i32,
|
ttlp: *mut i32,
|
||||||
) -> nss_status {
|
) -> nss_status {
|
||||||
set_if_valid(errnop, errno::from_i32(0));
|
set_if_valid(errnop, nix::errno::from_i32(0));
|
||||||
set_if_valid(h_errnop, HErrno::Success);
|
set_if_valid(h_errnop, HErrno::Success);
|
||||||
|
|
||||||
match block_on(async {
|
match block_on(async {
|
||||||
|
|
|
@ -11,8 +11,8 @@ use {
|
||||||
once_cell::sync::Lazy,
|
once_cell::sync::Lazy,
|
||||||
std::collections::HashMap,
|
std::collections::HashMap,
|
||||||
std::net::{IpAddr, Ipv4Addr, Ipv6Addr},
|
std::net::{IpAddr, Ipv4Addr, Ipv6Addr},
|
||||||
std::time::Duration,
|
//std::time::Duration,
|
||||||
tokio::time::timeout,
|
//tokio::time::timeout,
|
||||||
};
|
};
|
||||||
|
|
||||||
static CLOUDFLARE_PARENTALCONTROL_ADDRS: Lazy<Vec<IpAddr>> = Lazy::new(|| {
|
static CLOUDFLARE_PARENTALCONTROL_ADDRS: Lazy<Vec<IpAddr>> = Lazy::new(|| {
|
||||||
|
@ -36,7 +36,7 @@ fork_test! {
|
||||||
fn application_dns_is_nxdomain() -> Result<()> {
|
fn application_dns_is_nxdomain() -> Result<()> {
|
||||||
common::setup()?;
|
common::setup()?;
|
||||||
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
||||||
let dbus = common::mock_dbus(HashMap::from([(
|
let _dbus = common::mock_dbus(HashMap::from([(
|
||||||
getuid(),
|
getuid(),
|
||||||
vec![CLOUDFLARE_PARENTALCONTROL_ADDRS.clone()],
|
vec![CLOUDFLARE_PARENTALCONTROL_ADDRS.clone()],
|
||||||
)]));
|
)]));
|
||||||
|
@ -61,7 +61,8 @@ fork_test! {
|
||||||
freeaddrinfo(addr);
|
freeaddrinfo(addr);
|
||||||
};
|
};
|
||||||
|
|
||||||
timeout(Duration::from_secs(1), dbus).await??
|
//timeout(Duration::from_secs(1), dbus).await??
|
||||||
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +71,7 @@ fork_test! {
|
||||||
common::setup()?;
|
common::setup()?;
|
||||||
|
|
||||||
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
||||||
let dbus = common::mock_dbus(HashMap::from([(
|
let _dbus = common::mock_dbus(HashMap::from([(
|
||||||
getuid(),
|
getuid(),
|
||||||
vec![CLOUDFLARE_PARENTALCONTROL_ADDRS.clone()],
|
vec![CLOUDFLARE_PARENTALCONTROL_ADDRS.clone()],
|
||||||
)]));
|
)]));
|
||||||
|
@ -83,7 +84,8 @@ fork_test! {
|
||||||
assert_eq!(system_addr, our_addr);
|
assert_eq!(system_addr, our_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout(Duration::from_secs(1), dbus).await??
|
//timeout(Duration::from_secs(1), dbus).await??
|
||||||
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +94,7 @@ fork_test! {
|
||||||
common::setup()?;
|
common::setup()?;
|
||||||
|
|
||||||
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
||||||
let dbus = common::mock_dbus(HashMap::from([(
|
let _dbus = common::mock_dbus(HashMap::from([(
|
||||||
getuid(),
|
getuid(),
|
||||||
vec![CLOUDFLARE_PARENTALCONTROL_ADDRS.clone()],
|
vec![CLOUDFLARE_PARENTALCONTROL_ADDRS.clone()],
|
||||||
)]));
|
)]));
|
||||||
|
@ -108,7 +110,8 @@ fork_test! {
|
||||||
assert_ne!(system_addr, our_addr);
|
assert_ne!(system_addr, our_addr);
|
||||||
assert_eq!(our_addr, IpAddr::V6(Ipv6Addr::UNSPECIFIED));
|
assert_eq!(our_addr, IpAddr::V6(Ipv6Addr::UNSPECIFIED));
|
||||||
|
|
||||||
timeout(Duration::from_secs(1), dbus).await??
|
//timeout(Duration::from_secs(1), dbus).await??
|
||||||
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +120,7 @@ fork_test! {
|
||||||
common::setup()?;
|
common::setup()?;
|
||||||
|
|
||||||
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
||||||
let dbus = common::mock_dbus(HashMap::from([(getuid(), vec![ /* no restriction */])]));
|
let _dbus = common::mock_dbus(HashMap::from([(getuid(), vec![ /* no restriction */])]));
|
||||||
|
|
||||||
const HOSTNAME: &str = "pornhub.com";
|
const HOSTNAME: &str = "pornhub.com";
|
||||||
|
|
||||||
|
@ -127,7 +130,8 @@ fork_test! {
|
||||||
assert_eq!(system_addr, our_addr);
|
assert_eq!(system_addr, our_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout(Duration::from_secs(1), dbus).await??
|
//timeout(Duration::from_secs(1), dbus).await??
|
||||||
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue